64 #define DEFAULT_HEATMAP_W 32 
   65 #define DEFAULT_HEATMAP_H 16 
   67 #define M_PI_F ((float)M_PI) 
   68 #define M_PI_2_F ((float)M_PI_2) 
   69 #define M_PI_4_F ((float)M_PI_4) 
   70 #define M_SQRT2_F ((float)M_SQRT2) 
   72 #define DEFAULT_EXPANSION_COEF 1.01f 
   74 #define BARREL_THETA_RANGE (DEFAULT_EXPANSION_COEF *  2.0f * M_PI_F) 
   75 #define BARREL_PHI_RANGE   (DEFAULT_EXPANSION_COEF *  M_PI_2_F) 
   78 #define FIXED_POINT_PRECISION 16 
   81 #define SSIM360_HIST_SIZE 131072 
   85     1.0, 0.9, 0.8, 0.7, 0.6,
 
   86     0.5, 0.4, 0.3, 0.2, 0.1, 0, -1
 
  196         uint8_t *
main, 
int main_stride,
 
  197         uint8_t *
ref, 
int ref_stride,
 
  202 #define OFFSET(x) offsetof(SSIM360Context, x) 
  203 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM 
  206     { 
"stats_file", 
"Set file where to store per-frame difference information",
 
  208     { 
"f",          
"Set file where to store per-frame difference information",
 
  212       "Specifies if non-luma channels must be computed",
 
  214       0, 1, .flags = 
FLAGS },
 
  216     { 
"frame_skip_ratio",
 
  217       "Specifies the number of frames to be skipped from evaluation, for every evaluated frame",
 
  219       0, 1000000, .flags = 
FLAGS },
 
  221     { 
"ref_projection", 
"projection of the reference video",
 
  232     { 
"main_projection", 
"projection of the main video",
 
  236     { 
"ref_stereo", 
"stereo format of the reference video",
 
  244     { 
"main_stereo", 
"stereo format of main video",
 
  249       "Expansion (padding) coefficient for each cube face of the reference video",
 
  253       "Expansion (padding) coefficient for each cube face of the main video",
 
  257       "Specifies if the tape based SSIM 360 algorithm must be used independent of the input video types",
 
  259       0, 1, .flags = 
FLAGS },
 
  262       "Heatmap data for view-based evaluation. For heatmap file format, please refer to EntSphericalVideoHeatmapData.",
 
  265     { 
"default_heatmap_width",
 
  266       "Default heatmap dimension. Will be used when dimension is not specified in heatmap data.",
 
  269     { 
"default_heatmap_height",
 
  270       "Default heatmap dimension. Will be used when dimension is not specified in heatmap data.",
 
  343                     const uint8_t *ref8,  ptrdiff_t ref_stride,
 
  346     const uint16_t *main16 = (
const uint16_t *)main8;
 
  347     const uint16_t *ref16  = (
const uint16_t *)ref8;
 
  352     for (
int z = 0; z < 
width; z++) {
 
  353         uint64_t s1 = 0, s2 = 0, 
ss = 0, s12 = 0;
 
  355         for (
int y = 0; y < 4; y++) {
 
  356             for (
int x = 0; x < 4; x++) {
 
  357                 unsigned a = main16[x + y * main_stride];
 
  358                 unsigned b = ref16[x + y * ref_stride];
 
  379                    const uint8_t *
ref,  ptrdiff_t ref_stride,
 
  380                    int (*sums)[4], 
int width)
 
  382     for (
int z = 0; z < 
width; z++) {
 
  383         uint32_t s1 = 0, s2 = 0, 
ss = 0, s12 = 0;
 
  385         for (
int y = 0; y < 4; y++) {
 
  386             for (
int x = 0; x < 4; x++) {
 
  387                 int a = 
main[x + y * main_stride];
 
  388                 int b = 
ref[x + y * ref_stride];
 
  417     int64_t covar = fs12 * 64 - fs1 * fs2;
 
  419     return (
float)(2 * fs1 * fs2 + ssim_c1) * (
float)(2 * covar + ssim_c2)
 
  420          / ((
float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (
float)(
vars + ssim_c2));
 
  425     static const int ssim_c1 = (int)(.01*.01*255*255*64 + .5);
 
  426     static const int ssim_c2 = (int)(.03*.03*255*255*64*63 + .5);
 
  432     int vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
 
  433     int covar = fs12 * 64 - fs1 * fs2;
 
  435     return (
float)(2 * fs1 * fs2 + ssim_c1) * (
float)(2 * covar + ssim_c2)
 
  436          / ((
float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (
float)(
vars + ssim_c2));
 
  442                    double *density_map, 
int map_width, 
double *total_weight)
 
  444     double ssim360 = 0.0, 
weight;
 
  447         weight = density_map ? density_map[(int) ((0.5 + 
i) / 
width * map_width)] : 1.0;
 
  449             sum0[
i][0] + sum0[
i + 1][0] + sum1[
i][0] + sum1[
i + 1][0],
 
  450             sum0[
i][1] + sum0[
i + 1][1] + sum1[
i][1] + sum1[
i + 1][1],
 
  451             sum0[
i][2] + sum0[
i + 1][2] + sum1[
i][2] + sum1[
i + 1][2],
 
  452             sum0[
i][3] + sum0[
i + 1][3] + sum1[
i][3] + sum1[
i + 1][3],
 
  461                   double *density_map, 
int map_width, 
double *total_weight)
 
  463     double ssim360 = 0.0, 
weight;
 
  466         weight = density_map ? density_map[(int) ((0.5 + 
i) / 
width * map_width)] : 1.0;
 
  468             sum0[
i][0] + sum0[
i + 1][0] + sum1[
i][0] + sum1[
i + 1][0],
 
  469             sum0[
i][1] + sum0[
i + 1][1] + sum1[
i][1] + sum1[
i + 1][1],
 
  470             sum0[
i][2] + sum0[
i + 1][2] + sum1[
i][2] + sum1[
i + 1][2],
 
  471             sum0[
i][3] + sum0[
i + 1][3] + sum1[
i][3] + sum1[
i + 1][3]);
 
  479                     uint8_t *
ref, 
int ref_stride,
 
  484     double ssim360 = 0.0;
 
  487     double total_weight = 0.0;
 
  492     for (
int y = 1; y < 
height; y++) {
 
  493         for (; z <= y; z++) {
 
  494             FFSWAP(
void*, sum0, sum1);
 
  496                                 &
ref[4 * z * ref_stride], ref_stride,
 
  503             density.
w, &total_weight);
 
  506     return (
double) (ssim360 / total_weight);
 
  511                    uint8_t *
ref, 
int ref_stride,
 
  516     double ssim360 = 0.0;
 
  517     int (*sum0)[4] = 
temp;
 
  518     int (*sum1)[4] = sum0 + (
width >> 2) + 3;
 
  519     double total_weight = 0.0;
 
  524     for (
int y = 1; y < 
height; y++) {
 
  525         for (; z <= y; z++) {
 
  526             FFSWAP(
void*, sum0, sum1);
 
  528                 &
main[4 * z * main_stride], main_stride,
 
  529                 &
ref[4 * z * ref_stride], ref_stride,
 
  533             (
const int (*)[4])sum0, (
const int (*)[4])sum1, 
width - 1,
 
  535             density.
w, &total_weight);
 
  538     return (
double) (ssim360 / total_weight);
 
  549     static const int inv_byte_mask = UINT_MAX << 8;
 
  551     int tl, tr, bl, br, v;
 
  553     if (max_value & inv_byte_mask) {
 
  554         uint16_t *data16 = (uint16_t *)
data;
 
  578                    int offset_y, 
int max_value, 
int (*sums)[4])
 
  583     for (
int z = 0; z < 2; z++) {
 
  584         int s1 = 0, s2 = 0, 
ss = 0, s12 = 0;
 
  587         for (
int y = offset_y; y < offset_y + 4; y++) {
 
  588             int y_stride = y << 3;
 
  589             for (
int x = offset_x; x < offset_x + 4; x++) {
 
  590                 int map_index = x + y_stride;
 
  613     int floor_theta_by_2pi, floor_theta_by_pi;
 
  616     floor_theta_by_2pi = (int)(theta / (2.0
f * 
M_PI_F)) - (theta < 0.0
f);
 
  617     theta -= 2.0f * 
M_PI_F * floor_theta_by_2pi;
 
  620     floor_theta_by_pi = theta / 
M_PI_F;
 
  621     theta -= 2.0f * 
M_PI_F * floor_theta_by_pi;
 
  627     float pitch, yaw, norm_pitch, norm_yaw;
 
  633     pitch = asinf(norm_tape_pos*2);
 
  634     yaw   = 
M_PI_2_F * pitch / angular_resoluation;
 
  638     norm_pitch = 1.0f - (pitch / 
M_PI_F + 0.5f);
 
  639     norm_yaw   = yaw / 2.0f / 
M_PI_F + 0.5f;
 
  650              int tape_length, 
int max_value, 
void *
temp,
 
  651              double *ssim360_hist, 
double *ssim360_hist_net,
 
  654     int horizontal_block_count = 2;
 
  655     int vertical_block_count = tape_length >> 2;
 
  659     double ssim360 = 0.0;
 
  660     double sum_weight = 0.0;
 
  662     int (*sum0)[4] = 
temp;
 
  663     int (*sum1)[4] = sum0 + horizontal_block_count + 3;
 
  665     for (y = 1; y < vertical_block_count; y++) {
 
  666         int fs1, fs2, fss, fs12, hist_index;
 
  667         float norm_tape_pos, 
weight;
 
  668         double sample_ssim360;
 
  670         for (; z <= y; z++) {
 
  671             FFSWAP(
void*, sum0, sum1);
 
  676         fs1  = sum0[0][0] + sum0[1][0] + sum1[0][0] + sum1[1][0];
 
  677         fs2  = sum0[0][1] + sum0[1][1] + sum1[0][1] + sum1[1][1];
 
  678         fss  = sum0[0][2] + sum0[1][2] + sum1[0][2] + sum1[1][2];
 
  679         fs12 = sum0[0][3] + sum0[1][3] + sum1[0][3] + sum1[1][3];
 
  681         if (max_value > 255) {
 
  683             double ssim_c1_d = .01*.01*64*max_value*max_value;
 
  684             double ssim_c2_d = .03*.03*64*63*max_value*max_value;
 
  686             double vars = 64. * fss - 1. * fs1 * fs1 - 1. * fs2 * fs2;
 
  687             double covar = 64. * fs12 - 1.*fs1 * fs2;
 
  688             sample_ssim360 = (2. * fs1 * fs2 + ssim_c1_d) * (2. * covar + ssim_c2_d)
 
  689                         / ((1. * fs1 * fs1 + 1. * fs2 * fs2 + ssim_c1_d) * (1. * 
vars + ssim_c2_d));
 
  691             static const int ssim_c1 = (int)(.01*.01*255*255*64 + .5);
 
  692             static const int ssim_c2 = (int)(.03*.03*255*255*64*63 + .5);
 
  694             int vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
 
  695             int covar = fs12 * 64 - fs1 * fs2;
 
  696             sample_ssim360 = (
double)(2 * fs1 * fs2 + ssim_c1) * (
double)(2 * covar + ssim_c2)
 
  703         norm_tape_pos = (y - 0.5f) / (vertical_block_count - 1.0
f) - 0.5f;
 
  706         ssim360_hist[hist_index] += 
weight;
 
  707         *ssim360_hist_net += 
weight;
 
  709         ssim360 += (sample_ssim360 * 
weight);
 
  713     return ssim360 / sum_weight;
 
  722     float x_image = 
av_clipf(x * 
p->x_image_range, 0, 
p->x_image_range) + 
p->x_image_offset;
 
  723     float y_image = 
av_clipf(y * 
p->y_image_range, 0, 
p->y_image_range) + 
p->y_image_offset;
 
  725     int x_floor = x_image;
 
  726     int y_floor = y_image;
 
  727     float x_diff = x_image - x_floor;
 
  728     float y_diff = y_image - y_floor;
 
  730     int x_ceil = x_floor + (x_diff > 1e-6);
 
  731     int y_ceil = y_floor + (y_diff > 1e-6);
 
  732     float x_inv_diff = 1.0f - x_diff;
 
  733     float y_inv_diff = 1.0f - y_diff;
 
  736     m->
tli = x_floor    + y_floor   * 
p->stride;
 
  737     m->
tri = x_ceil     + y_floor   * 
p->stride;
 
  738     m->
bli = x_floor    + y_ceil    * 
p->stride;
 
  739     m->
bri = x_ceil     + y_ceil    * 
p->stride;
 
  742     m->
tlf = x_inv_diff * y_inv_diff * fixed_point_scale;
 
  743     m->
trf = x_diff     * y_inv_diff * fixed_point_scale;
 
  744     m->
blf = x_inv_diff * y_diff     * fixed_point_scale;
 
  745     m->
brf = x_diff     * y_diff     * fixed_point_scale;
 
  750     *x = 0.5f + theta / (2.0f * 
M_PI_F);
 
  757     float abs_phi = 
FFABS(phi);
 
  768         float circle_x = radial_ratio * 
sinf(theta);
 
  769         float circle_y = radial_ratio * 
cosf(theta);
 
  770         float offset_y = 0.25f;
 
  777         *x = 0.8f + 0.1f * (1.0f + circle_x);
 
  778         *y = offset_y + 0.25f * circle_y;
 
  784     float abs_phi = 
FFABS(phi);
 
  788     float radian_pi_theta = theta / 
M_PI_F + 0.5f;
 
  791     if (radian_pi_theta < 0.0
f)
 
  792         radian_pi_theta += 2.0f;
 
  795     vFace = radian_pi_theta >= 1.0f;
 
  799         *x = 2.0f / 3.0f * (0.5f + (radian_pi_theta - vFace - 0.5f) / expand_coef);
 
  801         *y = 0.25f + 0.5f * vFace - phi / (
M_PI_F * expand_coef);
 
  805         float radial_ratio = 
cosf(abs_phi) /  (
sinf(abs_phi) * expand_coef);
 
  806         float circle_x = radial_ratio * 
sinf(theta);
 
  807         float circle_y = radial_ratio * 
cosf(theta);
 
  808         float offset_y = 0.25f;
 
  813             circle_y = (circle_y >= 0.0f) ? (1 - circle_y) : (-1 - circle_y);
 
  826         *x = 2.0f / 3.0f + 0.5f / 3.0f * (1.0f + circle_x);
 
  827         *y = offset_y + 0.25f * circle_y / expand_coef;  
 
  832 static int get_cubemap_face_map(
float axis_vec_x, 
float axis_vec_y, 
float axis_vec_z, 
float *face_x, 
float *face_y)
 
  839     if (
FFABS(axis_vec_y) > 0.577
f) {
 
  840         float x_hit = axis_vec_x / 
FFABS(axis_vec_y);
 
  841         float z_hit = axis_vec_z / axis_vec_y;
 
  852     if (
FFABS(axis_vec_x) > 0.577
f) {
 
  853         float z_hit = -axis_vec_z / axis_vec_x;
 
  854         float y_hit = axis_vec_y / 
FFABS(axis_vec_x);
 
  865     *face_x = axis_vec_x / axis_vec_z;
 
  867     *face_y = -axis_vec_y / 
FFABS(axis_vec_z);
 
  878     static const int face_projection_map[] = {
 
  883     float axis_vec_x = 
cosf(phi) * 
sinf(theta);
 
  884     float axis_vec_y = 
sinf(phi);
 
  885     float axis_vec_z = 
cosf(phi) * 
cosf(theta);
 
  886     float face_x = 0, face_y = 0;
 
  889     float x_offset = 1.f / 3.f * (face_projection_map[face_index] % 3);
 
  890     float y_offset = .5f * (face_projection_map[face_index] / 3);
 
  903     static const int face_projection_map[] = {
 
  909     float axis_yaw_vec_x, axis_yaw_vec_y, axis_yaw_vec_z;
 
  910     float axis_pitch_vec_z, axis_pitch_vec_y;
 
  911     float x_offset, y_offset;
 
  912     float face_x = 0, face_y = 0;
 
  920     axis_yaw_vec_x = 
cosf(phi) * 
sinf(theta);
 
  921     axis_yaw_vec_y = 
sinf(phi);
 
  922     axis_yaw_vec_z = 
cosf(phi) * 
cosf(theta);
 
  925     axis_pitch_vec_z = (axis_yaw_vec_z - axis_yaw_vec_y) / 
M_SQRT2_F;
 
  926     axis_pitch_vec_y = (axis_yaw_vec_y + axis_yaw_vec_z) / 
M_SQRT2_F;
 
  928     face_index = 
get_cubemap_face_map(axis_yaw_vec_x, axis_pitch_vec_y, axis_pitch_vec_z, &face_x, &face_y);
 
  931     if (face_index == 
LEFT || face_index == 
FRONT || face_index == 
RIGHT) {
 
  933         float upright_y = face_y;
 
  936     } 
else if (face_index == 
TOP || face_index == 
BOTTOM) {
 
  942     x_offset = .5f * (face_projection_map[face_index] & 1);
 
  943     y_offset = 1.f / 3.f * (face_projection_map[face_index] >> 1);
 
  945     *x = x_offset + (face_x / expand_coef + 1.f) / 4.
f;
 
  946     *y = y_offset + (face_y / expand_coef + 1.f) / 6.
f;
 
  952     switch(
p->projection) {
 
 1000         return expand_coef / (
M_SQRT2_F * image_width / 4.f);
 
 1007         return FFMAX((expand_coef * 
M_PI_F) / (2.0
f / 3.0
f * image_width),
 
 1008                      expand_coef * 
M_PI_2_F / (image_height / 2.0
f));
 
 1023     int ref_image_height = ref_sample_params->
y_image_range + 1;
 
 1025     float angular_resolution =
 
 1027                                     ref_image_width, ref_image_height);
 
 1029     float conversion_factor = 
M_PI_2_F / (angular_resolution * angular_resolution);
 
 1030     float start_phi = -
M_PI_2_F + 4.0f * angular_resolution;
 
 1031     float start_x = conversion_factor * 
sinf(start_phi);
 
 1032     float end_phi = 
M_PI_2_F - 3.0f * angular_resolution;
 
 1033     float end_x = conversion_factor * 
sinf(end_phi);
 
 1034     float x_range = end_x - start_x;
 
 1037     int tape_length = 
s->tape_length[plane] = ((int)
ROUNDED_DIV(x_range, 4)) << 2;
 
 1041     if (!
s->ref_tape_map[plane][eye] || !
s->main_tape_map[plane][eye])
 
 1044     s->angular_resolution[plane][eye] = angular_resolution;
 
 1047     for (
int y_index = 0; y_index < tape_length; y_index ++) {
 
 1048         int y_stride = y_index << 3;
 
 1050         float x = start_x + x_range * (y_index / (tape_length - 1.0f));
 
 1052         float mid_phi = asinf(x / conversion_factor);
 
 1054         float theta = mid_phi * 
M_PI_2_F / angular_resolution;
 
 1057         for (
int x_index = 0; x_index < 8; x_index ++) {
 
 1058             float phi = mid_phi + angular_resolution * (3.0f - x_index);
 
 1059             int tape_index = y_stride + x_index;
 
 1060             get_projected_map(phi, theta, ref_sample_params,  &
s->ref_tape_map [plane][eye][tape_index]);
 
 1061             get_projected_map(phi, theta, main_sample_params, &
s->main_tape_map[plane][eye][tape_index]);
 
 1072     int ref_stereo_format = 
s->ref_stereo_format;
 
 1073     int main_stereo_format = 
s->main_stereo_format;
 
 1075     int min_eye_count = 1 + are_both_stereo;
 
 1078     for (
int i = 0; 
i < 
s->nb_components; 
i ++) {
 
 1079         int ref_width = 
s->ref_planewidth[
i];
 
 1080         int ref_height = 
s->ref_planeheight[
i];
 
 1081         int main_width = 
s->main_planewidth[
i];
 
 1082         int main_height = 
s->main_planeheight[
i];
 
 1089         int ref_image_width = is_ref_LR ? ref_width >> 1 : ref_width;
 
 1090         int ref_image_height = is_ref_TB ? ref_height >> 1 : ref_height;
 
 1091         int main_image_width = is_main_LR ? main_width >> 1 : main_width;
 
 1092         int main_image_height = is_main_TB ? main_height >> 1 : main_height;
 
 1094         for (
int eye = 0; eye < min_eye_count; eye ++) {
 
 1097                 .planewidth     = ref_width,
 
 1098                 .planeheight    = ref_height,
 
 1099                 .x_image_range  = ref_image_width - 1,
 
 1100                 .y_image_range  = ref_image_height - 1,
 
 1101                 .x_image_offset = is_ref_LR * eye * ref_image_width,
 
 1102                 .y_image_offset = is_ref_TB * eye * ref_image_height,
 
 1103                 .projection     = 
s->ref_projection,
 
 1104                 .expand_coef    = 1.f + 
s->ref_pad,
 
 1109                 .planewidth     = main_width,
 
 1110                 .planeheight    = main_height,
 
 1111                 .x_image_range  = main_image_width - 1,
 
 1112                 .y_image_range  = main_image_height - 1,
 
 1113                 .x_image_offset = is_main_LR * eye * main_image_width,
 
 1114                 .y_image_offset = is_main_TB * eye * main_image_height,
 
 1115                 .projection     = 
s->main_projection,
 
 1116                 .expand_coef    = 1.f + 
s->main_pad,
 
 1134     double c[4], ssim360v = 0.0, ssim360p50 = 0.0;
 
 1136     int need_frame_skip = 
s->nb_net_frames % (
s->frame_skip_ratio + 1);
 
 1145     if (need_frame_skip)
 
 1150     if (
s->use_tape && !
s->tape_length[0]) {
 
 1156     for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1159                                 ref->data[
i],    
s->ref_tape_map [
i][0],
 
 1160                                 s->tape_length[
i], 
s->max, 
s->temp,
 
 1161                                 s->ssim360_hist[
i], &
s->ssim360_hist_net[
i],
 
 1162                                 s->angular_resolution[
i][0], 
s->heatmaps);
 
 1164             if (
s->ref_tape_map[
i][1]) {
 
 1166                                      ref->data[
i],    
s->ref_tape_map[
i][1],
 
 1167                                      s->tape_length[
i], 
s->max, 
s->temp,
 
 1168                                      s->ssim360_hist[
i], &
s->ssim360_hist_net[
i],
 
 1169                                      s->angular_resolution[
i][1], 
s->heatmaps);
 
 1175                                     s->ref_planewidth[
i], 
s->ref_planeheight[
i],
 
 1176                                     s->temp, 
s->max, 
s->density);
 
 1179         s->ssim360[
i] += 
c[
i];
 
 1180         ssim360v      += 
s->coefs[
i] * 
c[
i];
 
 1183     s->nb_ssim_frames++;
 
 1186         h_ptr = 
s->heatmaps;
 
 1187         s->heatmaps = 
s->heatmaps->next;
 
 1190     s->ssim360_total += ssim360v;
 
 1194         int hist_indices[4];
 
 1195         double hist_weight[4];
 
 1197         for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1203             for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1204                 double target_weight, ssim360p;
 
 1208                 target_weight = 
FFMAX(target_weight, 1);
 
 1209                 while(hist_indices[
i] >= 0 && hist_weight[
i] < target_weight) {
 
 1210                     hist_weight[
i] += 
s->ssim360_hist[
i][hist_indices[
i]];
 
 1216                     ssim360p50 += 
s->coefs[
i] * ssim360p;
 
 1217                 s->ssim360_percentile_sum[
i][
p] += ssim360p;
 
 1221         for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1223             s->ssim360_hist_net[
i] = 0;
 
 1226         for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1227             int cidx = 
s->is_rgb ? 
s->rgba_map[
i] : 
i;
 
 1235         if (
s->stats_file) {
 
 1236             fprintf(
s->stats_file, 
"n:%"PRId64
" ", 
s->nb_ssim_frames);
 
 1238             for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1239                 int cidx = 
s->is_rgb ? 
s->rgba_map[
i] : 
i;
 
 1240                 fprintf(
s->stats_file, 
"%c:%f ", 
s->comps[
i], 
c[cidx]);
 
 1243             fprintf(
s->stats_file, 
"All:%f (%f)\n", ssim360p50, 
ssim360_db(ssim360p50, 1.0));
 
 1251                           const char *
data, 
int w, 
int h)
 
 1269         char *saveptr, *
val;
 
 1317     if (
s->stats_file_str) {
 
 1318         if (!strcmp(
s->stats_file_str, 
"-")) {
 
 1319             s->stats_file = stdout;
 
 1322             if (!
s->stats_file) {
 
 1331     if (
s->use_tape && 
s->heatmap_str) {
 
 1333                              s->default_heatmap_w, 
s->default_heatmap_h);
 
 1348     s->main_planeheight[0] = 
inlink->h;
 
 1349     s->main_planeheight[3] = 
inlink->h;
 
 1353     s->main_planewidth[0]  = 
inlink->w;
 
 1354     s->main_planewidth[3]  = 
inlink->w;
 
 1360         s->main_projection = 
s->ref_projection;
 
 1364         s->main_stereo_format = 
s->ref_stereo_format;
 
 1371     double d, r_square, cos_square;
 
 1378     switch (
s->ref_stereo_format) {
 
 1387     switch (
s->ref_projection) {
 
 1389         for (
int i = 0; 
i < 
h; 
i++) {
 
 1390             d = cos(((0.5 + 
i) / 
h - 0.5) * 
M_PI);
 
 1391             for (
int j = 0; j < 
w; j++)
 
 1392                 s->density.value[
i * 
w + j] = d;
 
 1397         for (
int i = 0; 
i < 
h / 4; 
i++) {
 
 1398             for (
int j = 0; j < 
w / 6; j++) {
 
 1401                   (0.5 + 
i) / (
h / 2) * (0.5 + 
i) / (
h / 2) +
 
 1402                   (0.5 + j) / (
w / 3) * (0.5 + j) / (
w / 3);
 
 1404                 cos_square = 0.25 / (r_square + 0.25);
 
 1405                 d = pow(cos_square, 1.5);
 
 1407                 for (
int face = 0; face < 6; face++) {
 
 1420                         ow = 
w / 6 + 2 * 
w / 3;
 
 1432                         ow = 
w / 6 + 2 * 
w / 3;
 
 1435                     s->density.value[(oh - 1 - 
i) * 
w + ow - 1 - j] = d;
 
 1436                     s->density.value[(oh - 1 - 
i) * 
w + ow     + j] = d;
 
 1437                     s->density.value[(oh     + 
i) * 
w + ow - 1 - j] = d;
 
 1438                     s->density.value[(oh     + 
i) * 
w + ow     + j] = d;
 
 1445         for (
int i = 0; 
i < 
h / 6; 
i++) {
 
 1446             for (
int j = 0; j < 
w / 4; j++) {
 
 1449                     (0.5 + 
i) / (
h / 3) * (0.5 + 
i) / (
h / 3) +
 
 1450                     (0.5 + j) / (
w / 2) * (0.5 + j) / (
w / 2);
 
 1451                 r_square /= (1.f + 
s->ref_pad) * (1.
f + 
s->ref_pad);
 
 1452                 cos_square = 0.25 / (r_square + 0.25);
 
 1453                 d = pow(cos_square, 1.5);
 
 1455                 for (
int face = 0; face < 6; face++) {
 
 1468                         oh = 
h / 6 + 2 * 
h / 3;
 
 1480                         oh = 
h / 6 + 2 * 
h / 3;
 
 1483                   s->density.value[(oh - 1 - 
i) * 
w + ow - 1 - j] = d;
 
 1484                   s->density.value[(oh - 1 - 
i) * 
w + ow     + j] = d;
 
 1485                   s->density.value[(oh     + 
i) * 
w + ow - 1 - j] = d;
 
 1486                   s->density.value[(oh     + 
i) * 
w + ow     + j] = d;
 
 1493         for (
int i = 0; 
i < 
h; 
i++) {
 
 1494             for (
int j = 0; j < 
w * 4 / 5; j++) {
 
 1496                 s->density.value[
i * 
w + j] = d * d * d;
 
 1500         for (
int i = 0; 
i < 
h; 
i++) {
 
 1501             for (
int j = 
w * 4 / 5; j < 
w; j++) {
 
 1503                 double dx_squared = dx * dx;
 
 1506                 double top_dy_squared = top_dy * top_dy;
 
 1509                 double bottom_dy_squared = bottom_dy * bottom_dy;
 
 1512                 r_square = (
i < 
h / 2 ? top_dy_squared : bottom_dy_squared) + dx_squared;
 
 1516                 cos_square = 1.0 / (r_square + 1.0);
 
 1517                 d = pow(cos_square, 1.5);
 
 1518                 s->density.value[
i * 
w + j] = d;
 
 1524         for (
int i = 0; 
i < 
h; 
i++) {
 
 1525             for (
int j = 0; j < 
w; j++)
 
 1526                 s->density.value[
i * 
w + j] = 0;
 
 1530     switch (
s->ref_stereo_format) {
 
 1532         for (
int i = 0; 
i < 
h; 
i++) {
 
 1533             for (
int j = 0; j < 
w; j++)
 
 1534                 s->density.value[(
i + 
h) * 
w + j] = 
s->density.value[
i * 
w + j];
 
 1538         for (
int i = 0; 
i < 
h; 
i++) {
 
 1539             for (
int j = 0; j < 
w; j++)
 
 1540                 s->density.value[
i * 
w + j + 
w] = 
s->density.value[
i * 
w + j];
 
 1554     s->nb_components = 
desc->nb_components;
 
 1556     s->ref_planeheight[0] = 
inlink->h;
 
 1557     s->ref_planeheight[3] = 
inlink->h;
 
 1561     s->ref_planewidth[0]  = 
inlink->w;
 
 1562     s->ref_planewidth[3]  = 
inlink->w;
 
 1567     s->comps[0] = 
s->is_rgb ? 
'R' : 
'Y';
 
 1568     s->comps[1] = 
s->is_rgb ? 
'G' : 
'U';
 
 1569     s->comps[2] = 
s->is_rgb ? 
'B' : 
'V';
 
 1573     if (!
s->is_rgb && !
s->compute_chroma)
 
 1574         s->nb_components = 1;
 
 1576     s->max = (1 << 
desc->comp[0].depth) - 1;
 
 1580     for (
int i = 0; 
i < 
s->nb_components; 
i++)
 
 1581         sum += 
s->ref_planeheight[
i] * 
s->ref_planewidth[
i];
 
 1582     for (
int i = 0; 
i < 
s->nb_components; 
i++)
 
 1583         s->coefs[
i] = (
double) 
s->ref_planeheight[
i] * 
s->ref_planewidth[
i] / sum;
 
 1600     if (
ctx->inputs[0]->w != 
ctx->inputs[1]->w || 
ctx->inputs[0]->h != 
ctx->inputs[1]->h ||
 
 1601         s->ref_projection != 
s->main_projection || 
s->ref_stereo_format != 
s->main_stereo_format)
 
 1618         memset(
s->ssim360_percentile_sum, 0, 
sizeof(
s->ssim360_percentile_sum));
 
 1620         for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1622             if (!
s->ssim360_hist[
i])
 
 1630         if (!
s->density.value) {
 
 1641     outlink->
w = mainlink->
w;
 
 1642     outlink->
h = mainlink->
h;
 
 1647     s->fs.opt_shortest   = 1;
 
 1648     s->fs.opt_repeatlast = 1;
 
 1667     if (
s->nb_ssim_frames > 0) {
 
 1671         for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1672             int c = 
s->is_rgb ? 
s->rgba_map[
i] : 
i;
 
 1673             av_strlcatf(buf, 
sizeof(buf), 
" %c:%f (%f)", 
s->comps[
i], 
s->ssim360[
c] / 
s->nb_ssim_frames,
 
 1677                s->ssim360_total / 
s->nb_ssim_frames, 
ssim360_db(
s->ssim360_total, 
s->nb_ssim_frames));
 
 1683                 for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1684                     int c = 
s->is_rgb ? 
s->rgba_map[
i] : 
i;
 
 1685                     double ssim360p = 
s->ssim360_percentile_sum[
i][
p] / (
double)(
s->nb_ssim_frames);
 
 1698     for (
int i = 0; 
i < 
s->nb_components; 
i++) {
 
 1699         for (
int eye = 0; eye < 2; eye++) {
 
 1708     if (
s->stats_file && 
s->stats_file != stdout)
 
 1709         fclose(
s->stats_file);
 
 1714 #define PF(suf) AV_PIX_FMT_YUV420##suf,  AV_PIX_FMT_YUV422##suf,  AV_PIX_FMT_YUV444##suf, AV_PIX_FMT_GBR##suf 
 1734         .name         = 
"reference",
 
 1749     .
p.
name        = 
"ssim360",
 
 1751     .p.priv_class  = &ssim360_class,
 
 1752     .preinit       = ssim360_framesync_preinit,