From d4c969bcaf9b7396eeae2e67b4c2236e5be8e4ac Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Mon, 22 Apr 2024 15:47:57 -0700 Subject: [PATCH 1/4] some feature extractors, namely ST-RRED produce values with a lot of leading zeros which are not handled by 0.6f, instead selectively use more digits in the output, but only if required to maintain compatibility --- libvmaf/src/output.c | 103 ++++++++++++++++++++++++++++++++++++------- libvmaf/src/output.h | 2 + 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/libvmaf/src/output.c b/libvmaf/src/output.c index 0965939d8..890382ac5 100644 --- a/libvmaf/src/output.c +++ b/libvmaf/src/output.c @@ -44,6 +44,26 @@ static const char *pool_method_name[] = { [VMAF_POOL_METHOD_HARMONIC_MEAN] = "harmonic_mean", }; +int countLeadingZeroesFloat(double x) +{ + if(x < 0) + x = fabs(x); + + int intPart = (int)x; + double fractionalPart = x - intPart; + + // Count leading zeroes in the fractional part + int leadingZeroesCount = 0; + + while (fractionalPart < 1.0 && fractionalPart != 0) + { + fractionalPart *= 10; // Shift decimal point to the right + leadingZeroesCount++; + } + + return leadingZeroesCount; +} + int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, FILE *outfile, unsigned subsample, unsigned width, unsigned height, double fps, unsigned pic_cnt) @@ -58,6 +78,7 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, fprintf(outfile, " \n", fps); unsigned n_frames = 0; + int leadingZeroesCount; fprintf(outfile, " \n"); for (unsigned i = 0 ; i < max_capacity(fc); i++) { if ((subsample > 1) && (i % subsample)) @@ -78,10 +99,15 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, continue; if (!fc->feature_vector[j]->score[i].written) continue; - fprintf(outfile, "%s=\"%.6f\" ", - vmaf_feature_name_alias(fc->feature_vector[j]->name), - fc->feature_vector[j]->score[i].value - ); + leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); + if (leadingZeroesCount <= 6) + fprintf(outfile, "%s=\"%.6f\" ", + vmaf_feature_name_alias(fc->feature_vector[j]->name), + fc->feature_vector[j]->score[i].value); + else + fprintf(outfile, "%s=\"%.16f\" ", + vmaf_feature_name_alias(fc->feature_vector[j]->name), + fc->feature_vector[j]->score[i].value); } n_frames++; fprintf(outfile, "/>\n"); @@ -99,7 +125,13 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, int err = vmaf_feature_score_pooled(vmaf, feature_name, j, &score, 0, pic_cnt - 1); if (!err) - fprintf(outfile, "%s=\"%.6f\" ", pool_method_name[j], score); + { + leadingZeroesCount = countLeadingZeroesFloat(score); + if (leadingZeroesCount <= 6) + fprintf(outfile, "%s=\"%.6f\" ", pool_method_name[j], score); + else + fprintf(outfile, "%s=\"%.16f\" ", pool_method_name[j], score); + } } fprintf(outfile, "/>\n"); } @@ -108,7 +140,13 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, fprintf(outfile, " aggregate_vector.cnt; i++) { - fprintf(outfile, "%s=\"%.6f\" ", + leadingZeroesCount = countLeadingZeroesFloat(fc->aggregate_vector.metric[i].value); + if (leadingZeroesCount <= 6) + fprintf(outfile, "%s=\"%.6f\" ", + fc->aggregate_vector.metric[i].name, + fc->aggregate_vector.metric[i].value); + else + fprintf(outfile, "%s=\"%.16f\" ", fc->aggregate_vector.metric[i].name, fc->aggregate_vector.metric[i].value); } @@ -123,6 +161,7 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, FILE *outfile, unsigned subsample, double fps, unsigned pic_cnt) { + int leadingZeroesCount; fprintf(outfile, "{\n"); fprintf(outfile, " \"version\": \"%s\",\n", vmaf_version()); switch(fpclassify(fps)) { @@ -167,11 +206,18 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - fprintf(outfile, " \"%s\": %.6f%s\n", - vmaf_feature_name_alias(fc->feature_vector[j]->name), - fc->feature_vector[j]->score[i].value, - cnt2 < cnt ? "," : "" - ); + leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); + if (leadingZeroesCount <= 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: @@ -203,7 +249,12 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - fprintf(outfile, " \"%s\": %.6f", + leadingZeroesCount = countLeadingZeroesFloat((double)score); + if (leadingZeroesCount <= 6) + fprintf(outfile, " \"%s\": %.6f", + pool_method_name[j], score); + else + fprintf(outfile, " \"%s\": %.16f", pool_method_name[j], score); break; case FP_INFINITE: @@ -225,9 +276,17 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - fprintf(outfile, "\n \"%s\": %.6f", + leadingZeroesCount = countLeadingZeroesFloat(fc->aggregate_vector.metric[i].value); + if (leadingZeroesCount <= 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: @@ -246,7 +305,7 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, unsigned subsample) { - + int leadingZeroesCount; fprintf(outfile, "Frame,"); for (unsigned i = 0; i < fc->cnt; i++) { fprintf(outfile, "%s,", @@ -273,7 +332,12 @@ int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, continue; if (!fc->feature_vector[j]->score[i].written) continue; - fprintf(outfile, "%.6f,", fc->feature_vector[j]->score[i].value); + + leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); + if (leadingZeroesCount <= 6) + fprintf(outfile, "%.6f,", fc->feature_vector[j]->score[i].value); + else + fprintf(outfile, "%.16f,", fc->feature_vector[j]->score[i].value); } fprintf(outfile, "\n"); } @@ -284,6 +348,7 @@ int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, int vmaf_write_output_sub(VmafFeatureCollector *fc, FILE *outfile, unsigned subsample) { + int leadingZeroesCount; for (unsigned i = 0 ; i < max_capacity(fc); i++) { if ((subsample > 1) && (i % subsample)) continue; @@ -303,7 +368,13 @@ int vmaf_write_output_sub(VmafFeatureCollector *fc, FILE *outfile, continue; if (!fc->feature_vector[j]->score[i].written) continue; - fprintf(outfile, "%s: %.6f|", + leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); + if (leadingZeroesCount <= 6) + fprintf(outfile, "%s: %.6f|", + vmaf_feature_name_alias(fc->feature_vector[j]->name), + fc->feature_vector[j]->score[i].value); + else + fprintf(outfile, "%s: %.16f|", vmaf_feature_name_alias(fc->feature_vector[j]->name), fc->feature_vector[j]->score[i].value); } diff --git a/libvmaf/src/output.h b/libvmaf/src/output.h index 4c6e2a00c..31f11f5f7 100644 --- a/libvmaf/src/output.h +++ b/libvmaf/src/output.h @@ -19,6 +19,8 @@ #ifndef __VMAF_OUTPUT_H__ #define __VMAF_OUTPUT_H__ +int countLeadingZeroesFloat(float x); + int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, FILE *outfile, unsigned subsample, unsigned width, unsigned height, double fps, unsigned pic_cnt); From f49ecda2f34a3904dbb8c6c83923e0e4e9d2ca6a Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Tue, 23 Apr 2024 17:29:05 -0700 Subject: [PATCH 2/4] make function static and change to snake_case --- libvmaf/src/output.c | 52 ++++++++++++++++++++++---------------------- libvmaf/src/output.h | 2 -- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/libvmaf/src/output.c b/libvmaf/src/output.c index 890382ac5..cf3f2ff5b 100644 --- a/libvmaf/src/output.c +++ b/libvmaf/src/output.c @@ -44,8 +44,8 @@ static const char *pool_method_name[] = { [VMAF_POOL_METHOD_HARMONIC_MEAN] = "harmonic_mean", }; -int countLeadingZeroesFloat(double x) -{ +static int count_leading_zeros_flat(double x) +{ if(x < 0) x = fabs(x); @@ -53,15 +53,15 @@ int countLeadingZeroesFloat(double x) double fractionalPart = x - intPart; // Count leading zeroes in the fractional part - int leadingZeroesCount = 0; + int leading_zeros_count = 0; while (fractionalPart < 1.0 && fractionalPart != 0) { fractionalPart *= 10; // Shift decimal point to the right - leadingZeroesCount++; + leading_zeros_count++; } - return leadingZeroesCount; + return leading_zeros_count; } int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, @@ -78,7 +78,7 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, fprintf(outfile, " \n", fps); unsigned n_frames = 0; - int leadingZeroesCount; + int leading_zeros_count; fprintf(outfile, " \n"); for (unsigned i = 0 ; i < max_capacity(fc); i++) { if ((subsample > 1) && (i % subsample)) @@ -99,8 +99,8 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, continue; if (!fc->feature_vector[j]->score[i].written) continue; - leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + if (leading_zeros_count <= 6) fprintf(outfile, "%s=\"%.6f\" ", vmaf_feature_name_alias(fc->feature_vector[j]->name), fc->feature_vector[j]->score[i].value); @@ -126,8 +126,8 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, 0, pic_cnt - 1); if (!err) { - leadingZeroesCount = countLeadingZeroesFloat(score); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(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); @@ -140,8 +140,8 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, fprintf(outfile, " aggregate_vector.cnt; i++) { - leadingZeroesCount = countLeadingZeroesFloat(fc->aggregate_vector.metric[i].value); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(fc->aggregate_vector.metric[i].value); + if (leading_zeros_count <= 6) fprintf(outfile, "%s=\"%.6f\" ", fc->aggregate_vector.metric[i].name, fc->aggregate_vector.metric[i].value); @@ -161,7 +161,7 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, FILE *outfile, unsigned subsample, double fps, unsigned pic_cnt) { - int leadingZeroesCount; + int leading_zeros_count; fprintf(outfile, "{\n"); fprintf(outfile, " \"version\": \"%s\",\n", vmaf_version()); switch(fpclassify(fps)) { @@ -206,8 +206,8 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(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, @@ -249,8 +249,8 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - leadingZeroesCount = countLeadingZeroesFloat((double)score); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat((double)score); + if (leading_zeros_count <= 6) fprintf(outfile, " \"%s\": %.6f", pool_method_name[j], score); else @@ -276,8 +276,8 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - leadingZeroesCount = countLeadingZeroesFloat(fc->aggregate_vector.metric[i].value); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(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); @@ -298,14 +298,14 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, } fprintf(outfile, "\n }\n"); fprintf(outfile, "}\n"); - + return 0; } int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, unsigned subsample) { - int leadingZeroesCount; + int leading_zeros_count; fprintf(outfile, "Frame,"); for (unsigned i = 0; i < fc->cnt; i++) { fprintf(outfile, "%s,", @@ -333,8 +333,8 @@ int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, if (!fc->feature_vector[j]->score[i].written) continue; - leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + if (leading_zeros_count <= 6) fprintf(outfile, "%.6f,", fc->feature_vector[j]->score[i].value); else fprintf(outfile, "%.16f,", fc->feature_vector[j]->score[i].value); @@ -348,7 +348,7 @@ int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, int vmaf_write_output_sub(VmafFeatureCollector *fc, FILE *outfile, unsigned subsample) { - int leadingZeroesCount; + int leading_zeros_count; for (unsigned i = 0 ; i < max_capacity(fc); i++) { if ((subsample > 1) && (i % subsample)) continue; @@ -368,8 +368,8 @@ int vmaf_write_output_sub(VmafFeatureCollector *fc, FILE *outfile, continue; if (!fc->feature_vector[j]->score[i].written) continue; - leadingZeroesCount = countLeadingZeroesFloat(fc->feature_vector[j]->score[i].value); - if (leadingZeroesCount <= 6) + leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + if (leading_zeros_count <= 6) fprintf(outfile, "%s: %.6f|", vmaf_feature_name_alias(fc->feature_vector[j]->name), fc->feature_vector[j]->score[i].value); diff --git a/libvmaf/src/output.h b/libvmaf/src/output.h index 31f11f5f7..4c6e2a00c 100644 --- a/libvmaf/src/output.h +++ b/libvmaf/src/output.h @@ -19,8 +19,6 @@ #ifndef __VMAF_OUTPUT_H__ #define __VMAF_OUTPUT_H__ -int countLeadingZeroesFloat(float x); - int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, FILE *outfile, unsigned subsample, unsigned width, unsigned height, double fps, unsigned pic_cnt); From 538732bdfc253cbc280be8c783bebb248ace8473 Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Tue, 23 Apr 2024 22:09:08 -0700 Subject: [PATCH 3/4] more snake_case --- libvmaf/src/output.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libvmaf/src/output.c b/libvmaf/src/output.c index cf3f2ff5b..0500e4236 100644 --- a/libvmaf/src/output.c +++ b/libvmaf/src/output.c @@ -49,15 +49,15 @@ static int count_leading_zeros_flat(double x) if(x < 0) x = fabs(x); - int intPart = (int)x; - double fractionalPart = x - intPart; + int int_part = (int)x; + double fractional_part = x - int_part; // Count leading zeroes in the fractional part int leading_zeros_count = 0; - while (fractionalPart < 1.0 && fractionalPart != 0) + while (fractional_part < 1.0 && fractional_part != 0) { - fractionalPart *= 10; // Shift decimal point to the right + fractional_part *= 10; // Shift decimal point to the right leading_zeros_count++; } From dc5da99758720083d5358b84e24febaadef855c2 Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Tue, 23 Apr 2024 22:13:04 -0700 Subject: [PATCH 4/4] rename to count_leading_zeros_d --- libvmaf/src/output.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libvmaf/src/output.c b/libvmaf/src/output.c index 0500e4236..039657ff7 100644 --- a/libvmaf/src/output.c +++ b/libvmaf/src/output.c @@ -44,7 +44,7 @@ static const char *pool_method_name[] = { [VMAF_POOL_METHOD_HARMONIC_MEAN] = "harmonic_mean", }; -static int count_leading_zeros_flat(double x) +static int count_leading_zeros_d(double x) { if(x < 0) x = fabs(x); @@ -99,7 +99,7 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, continue; if (!fc->feature_vector[j]->score[i].written) continue; - leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + leading_zeros_count = count_leading_zeros_d(fc->feature_vector[j]->score[i].value); if (leading_zeros_count <= 6) fprintf(outfile, "%s=\"%.6f\" ", vmaf_feature_name_alias(fc->feature_vector[j]->name), @@ -126,7 +126,7 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, 0, pic_cnt - 1); if (!err) { - leading_zeros_count = count_leading_zeros_flat(score); + leading_zeros_count = count_leading_zeros_d(score); if (leading_zeros_count <= 6) fprintf(outfile, "%s=\"%.6f\" ", pool_method_name[j], score); else @@ -140,7 +140,7 @@ int vmaf_write_output_xml(VmafContext *vmaf, VmafFeatureCollector *fc, fprintf(outfile, " aggregate_vector.cnt; i++) { - leading_zeros_count = count_leading_zeros_flat(fc->aggregate_vector.metric[i].value); + leading_zeros_count = count_leading_zeros_d(fc->aggregate_vector.metric[i].value); if (leading_zeros_count <= 6) fprintf(outfile, "%s=\"%.6f\" ", fc->aggregate_vector.metric[i].name, @@ -206,7 +206,7 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + 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), @@ -249,7 +249,7 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - leading_zeros_count = count_leading_zeros_flat((double)score); + leading_zeros_count = count_leading_zeros_d((double)score); if (leading_zeros_count <= 6) fprintf(outfile, " \"%s\": %.6f", pool_method_name[j], score); @@ -276,7 +276,7 @@ int vmaf_write_output_json(VmafContext *vmaf, VmafFeatureCollector *fc, case FP_NORMAL: case FP_ZERO: case FP_SUBNORMAL: - leading_zeros_count = count_leading_zeros_flat(fc->aggregate_vector.metric[i].value); + 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, @@ -333,7 +333,7 @@ int vmaf_write_output_csv(VmafFeatureCollector *fc, FILE *outfile, if (!fc->feature_vector[j]->score[i].written) continue; - leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + leading_zeros_count = count_leading_zeros_d(fc->feature_vector[j]->score[i].value); if (leading_zeros_count <= 6) fprintf(outfile, "%.6f,", fc->feature_vector[j]->score[i].value); else @@ -368,7 +368,7 @@ int vmaf_write_output_sub(VmafFeatureCollector *fc, FILE *outfile, continue; if (!fc->feature_vector[j]->score[i].written) continue; - leading_zeros_count = count_leading_zeros_flat(fc->feature_vector[j]->score[i].value); + leading_zeros_count = count_leading_zeros_d(fc->feature_vector[j]->score[i].value); if (leading_zeros_count <= 6) fprintf(outfile, "%s: %.6f|", vmaf_feature_name_alias(fc->feature_vector[j]->name),