int vmaf_write_output_json()

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;
}