in libvmaf/src/output.c [160:303]
int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc,
FILE *outfile, unsigned subsample, double fps,
unsigned pic_cnt)
{
int leading_zeros_count;
fprintf(outfile, "{\n");
fprintf(outfile, " \"version\": \"%s\",\n", vmaf_version());
switch(fpclassify(fps)) {
case FP_NORMAL:
case FP_ZERO:
case FP_SUBNORMAL:
fprintf(outfile, " \"fps\": %.2f,\n", fps);
break;
case FP_INFINITE:
case FP_NAN:
fprintf(outfile, " \"fps\": null,\n");
}
unsigned n_frames = 0;
fprintf(outfile, " \"frames\": [");
for (unsigned i = 0 ; i < max_capacity(fc); i++) {
if ((subsample > 1) && (i % subsample))
continue;
unsigned cnt = 0;
for (unsigned j = 0; j < fc->cnt; j++) {
if (i > fc->feature_vector[j]->capacity)
continue;
if (fc->feature_vector[j]->score[i].written)
cnt++;
}
if (!cnt) continue;
fprintf(outfile, "%s", i > 0 ? ",\n" : "\n");
fprintf(outfile, " {\n");
fprintf(outfile, " \"frameNum\": %d,\n", i);
fprintf(outfile, " \"metrics\": {\n");
unsigned cnt2 = 0;
for (unsigned j = 0; j < fc->cnt; j++) {
if (i > fc->feature_vector[j]->capacity)
continue;
if (!fc->feature_vector[j]->score[i].written)
continue;
cnt2++;
switch(fpclassify(fc->feature_vector[j]->score[i].value)) {
case FP_NORMAL:
case FP_ZERO:
case FP_SUBNORMAL:
leading_zeros_count = count_leading_zeros_d(fc->feature_vector[j]->score[i].value);
if (leading_zeros_count <= 6)
fprintf(outfile, " \"%s\": %.6f%s\n",
vmaf_feature_name_alias(fc->feature_vector[j]->name),
fc->feature_vector[j]->score[i].value,
cnt2 < cnt ? "," : "");
else
fprintf(outfile, " \"%s\": %.16f%s\n",
vmaf_feature_name_alias(fc->feature_vector[j]->name),
fc->feature_vector[j]->score[i].value,
cnt2 < cnt ? "," : "");
break;
case FP_INFINITE:
case FP_NAN:
fprintf(outfile, " \"%s\": null%s",
vmaf_feature_name_alias(fc->feature_vector[j]->name),
cnt2 < cnt ? "," : "");
break;
}
}
fprintf(outfile, " }\n");
fprintf(outfile, " }");
n_frames++;
}
fprintf(outfile, "\n ],\n");
fprintf(outfile, " \"pooled_metrics\": {");
for (unsigned i = 0; i < fc->cnt; i++) {
const char *feature_name = fc->feature_vector[i]->name;
fprintf(outfile, "%s", i > 0 ? ",\n" : "\n");
fprintf(outfile, " \"%s\": {",
vmaf_feature_name_alias(feature_name));
for (unsigned j = 1; j < VMAF_POOL_METHOD_NB; j++) {
double score;
int err = vmaf_feature_score_pooled(vmaf, feature_name, j, &score,
0, pic_cnt - 1);
if (!err) {
fprintf(outfile, "%s", j > 1 ? ",\n" : "\n");
switch(fpclassify(score)) {
case FP_NORMAL:
case FP_ZERO:
case FP_SUBNORMAL:
leading_zeros_count = count_leading_zeros_d((double)score);
if (leading_zeros_count <= 6)
fprintf(outfile, " \"%s\": %.6f",
pool_method_name[j], score);
else
fprintf(outfile, " \"%s\": %.16f",
pool_method_name[j], score);
break;
case FP_INFINITE:
case FP_NAN:
fprintf(outfile, " \"%s\": null",
pool_method_name[j]);
break;
}
}
}
fprintf(outfile, "\n");
fprintf(outfile, " }");
}
fprintf(outfile, "\n },\n");
fprintf(outfile, " \"aggregate_metrics\": {");
for (unsigned i = 0; i < fc->aggregate_vector.cnt; i++) {
switch(fpclassify(fc->aggregate_vector.metric[i].value)) {
case FP_NORMAL:
case FP_ZERO:
case FP_SUBNORMAL:
leading_zeros_count = count_leading_zeros_d(fc->aggregate_vector.metric[i].value);
if (leading_zeros_count <= 6)
fprintf(outfile, "\n \"%s\": %.6f",
fc->aggregate_vector.metric[i].name,
fc->aggregate_vector.metric[i].value);
else
fprintf(outfile, "\n \"%s\": %.16f",
fc->aggregate_vector.metric[i].name,
fc->aggregate_vector.metric[i].value);
break;
case FP_INFINITE:
case FP_NAN:
fprintf(outfile, "\n \"%s\": null",
fc->aggregate_vector.metric[i].name);
break;
}
fprintf(outfile, "%s", i < fc->aggregate_vector.cnt - 1 ? "," : "");
}
fprintf(outfile, "\n }\n");
fprintf(outfile, "}\n");
return 0;
}