diff --git a/libvmaf/include/libvmaf/libvmaf.h b/libvmaf/include/libvmaf/libvmaf.h index 11d0d1190..d723c2588 100644 --- a/libvmaf/include/libvmaf/libvmaf.h +++ b/libvmaf/include/libvmaf/libvmaf.h @@ -257,6 +257,7 @@ int vmaf_feature_score_at_index(VmafContext *vmaf, const char *feature_name, * Metadata structure. * * @param feature_name Name of the feature to fetch. + * vmaf going to take ownership of this string. * * @param picture_index Picture index. * @@ -285,6 +286,31 @@ typedef struct VmafMetadataConfiguration { void *data; } VmafMetadataConfiguration; + +/** + * Metadata flags. + * + * Features can provide additional metrics about the score. To propagate those, + * the `VmafMetadataFlags` enum should be used for specifying which information should be + * propagated to the metadata. + * + * @param VMAF_METADATA_FLAG_NONE No flags. + * + * @param VMAF_METADATA_FLAG_FEATURE Include all indivual metrics. + * + * @param VMAF_METADATA_FLAG_MODEL Propagate only model score. + * + * @param VMAF_METADATA_FLAG_FEATURE_NAME Propagate only given feature name.. + * + */ + +enum VmafMetadataFlags { + VMAF_METADATA_FLAG_NONE = 0, + VMAF_METADATA_FLAG_FEATURE = 1 << 0, + VMAF_METADATA_FLAG_MODEL = 1 << 1, + VMAF_METADATA_FLAG_FEATURE_NAME = 1 << 2, +}; + /** * Register a callback to receive VMAF metadata. * @@ -296,7 +322,20 @@ typedef struct VmafMetadataConfiguration { * @return 0 on success, or < 0 (a negative errno code) on error. */ -int vmaf_register_metadata_handler(VmafContext *vmaf, VmafMetadataConfiguration cfg); +int vmaf_register_metadata_handler(VmafContext *vmaf, VmafMetadataConfiguration cfg, uint64_t flags); + +/** + * Get the number of registered metadata handlers. + * + * @param vmaf The VMAF context allocated with `vmaf_init()`. + * + * @param count Number of registered metadata handlers. + * + * + * @return 0 on success, or < 0 (a negative errno code) on error. + */ + +int vmaf_get_metadata_handler_count(VmafContext *vmaf, unsigned *count); /** * Pooled VMAF score for a specific interval. diff --git a/libvmaf/src/feature/feature_collector.c b/libvmaf/src/feature/feature_collector.c index 2eb2ec643..888b7814a 100644 --- a/libvmaf/src/feature/feature_collector.c +++ b/libvmaf/src/feature/feature_collector.c @@ -27,6 +27,7 @@ #include "metadata_handler.h" #include "feature_collector.h" #include "feature_name.h" +#include "feature_extractor.h" #include "libvmaf/libvmaf.h" #include "log.h" #include "predict.h" @@ -290,6 +291,25 @@ int vmaf_feature_collector_register_metadata(VmafFeatureCollector *feature_colle return 0; } +int vmaf_feature_collector_get_metadata_count(VmafFeatureCollector *feature_collector, + unsigned *count) +{ + if (!feature_collector) return -EINVAL; + if (!count) return -EINVAL; + + VmafCallbackList *metadata = feature_collector->metadata; + unsigned cnt = 0; + VmafCallbackItem *iter = metadata ? metadata->head : NULL; + while (iter) { + cnt++; + iter = iter->next; + } + + *count = cnt; + + return 0; +} + static FeatureVector *find_feature_vector(VmafFeatureCollector *fc, const char *feature_name) { diff --git a/libvmaf/src/feature/feature_collector.h b/libvmaf/src/feature/feature_collector.h index 83745bf8c..8d07450bc 100644 --- a/libvmaf/src/feature/feature_collector.h +++ b/libvmaf/src/feature/feature_collector.h @@ -70,6 +70,9 @@ int vmaf_feature_collector_append(VmafFeatureCollector *feature_collector, int vmaf_feature_collector_register_metadata(VmafFeatureCollector *feature_collector, VmafMetadataConfiguration metadata_cfg); +int vmaf_feature_collector_get_metadata_count(VmafFeatureCollector *feature_collector, + unsigned *count); + int vmaf_feature_collector_append_with_dict(VmafFeatureCollector *fc, VmafDictionary *dict, const char *feature_name, double score, unsigned index); diff --git a/libvmaf/src/libvmaf.c b/libvmaf/src/libvmaf.c index 31340e22c..95338b20e 100644 --- a/libvmaf/src/libvmaf.c +++ b/libvmaf/src/libvmaf.c @@ -744,13 +744,36 @@ int vmaf_read_pictures(VmafContext *vmaf, VmafPicture *ref, VmafPicture *dist, return err; } -int vmaf_register_metadata_handler(VmafContext *vmaf, VmafMetadataConfiguration cfg) +int vmaf_register_metadata_handler(VmafContext *vmaf, VmafMetadataConfiguration cfg, uint64_t flags) { if (!vmaf) return -EINVAL; + if (flags & VMAF_METADATA_FLAG_FEATURE) { + VmafFeatureExtractor *fex = vmaf_get_feature_extractor_by_name(cfg.feature_name); + if (!fex) return -EINVAL; + int err = 0; + for (unsigned i = 0; fex->provided_features[i] != NULL; i++) { + VmafMetadataConfiguration new_cfg = { 0 }; + new_cfg.data = cfg.data; + new_cfg.callback = cfg.callback; + new_cfg.feature_name = strdup(fex->provided_features[i]); + err = vmaf_feature_collector_register_metadata(vmaf->feature_collector, new_cfg); + if (err) return err; + } + return 0; + } + return vmaf_feature_collector_register_metadata(vmaf->feature_collector, cfg); } +int vmaf_get_metadata_handler_count(VmafContext *vmaf, unsigned *count) +{ + if (!vmaf) return -EINVAL; + if (!count) return -EINVAL; + + return vmaf_feature_collector_get_metadata_count(vmaf->feature_collector, count); +} + int vmaf_feature_score_at_index(VmafContext *vmaf, const char *feature_name, double *score, unsigned index) { diff --git a/libvmaf/src/metadata_handler.c b/libvmaf/src/metadata_handler.c index 99f69c212..463571c69 100644 --- a/libvmaf/src/metadata_handler.c +++ b/libvmaf/src/metadata_handler.c @@ -69,6 +69,7 @@ int vmaf_metadata_destroy(VmafCallbackList *metadata) VmafCallbackItem *iter = metadata->head; while (iter) { VmafCallbackItem *next = iter->next; + free(iter->metadata_cfg.feature_name); free(iter); iter = next; } diff --git a/libvmaf/test/test_predict.c b/libvmaf/test/test_predict.c index 3fe970047..e3bc65378 100644 --- a/libvmaf/test/test_predict.c +++ b/libvmaf/test/test_predict.c @@ -88,7 +88,7 @@ static char* test_propagate_metadata() }; VmafMetadataConfiguration m = { - .feature_name = "vmaf", + .feature_name = strdup("vmaf"), .callback = set_meta, .data = &meta_data, }; @@ -127,6 +127,7 @@ static char* test_propagate_metadata() vmaf_feature_collector_destroy(feature_collector); m.data = NULL; + m.feature_name = strdup("vmaf"); err = vmaf_feature_collector_init(&feature_collector); mu_assert("problem during vmaf_feature_collector_init", !err); @@ -142,6 +143,7 @@ static char* test_propagate_metadata() vmaf_feature_collector_destroy(feature_collector); m.callback = NULL; + m.feature_name = strdup("vmaf"); err = vmaf_feature_collector_init(&feature_collector); mu_assert("problem during vmaf_feature_collector_init", !err);