2424#include <string.h>
2525
2626#include "dict.h"
27+ #include "metadata_handler.h"
2728#include "feature_collector.h"
2829#include "feature_name.h"
30+ #include "libvmaf/libvmaf.h"
2931#include "log.h"
32+ #include "predict.h"
3033
3134static int aggregate_vector_init (AggregateVector * aggregate_vector )
3235{
@@ -215,8 +218,12 @@ int vmaf_feature_collector_init(VmafFeatureCollector **const feature_collector)
215218 if (err ) goto free_feature_vector ;
216219 err = pthread_mutex_init (& (fc -> lock ), NULL );
217220 if (err ) goto free_aggregate_vector ;
221+ err = vmaf_metadata_init (& (fc -> metadata ));
222+ if (err ) goto free_mutex ;
218223 return 0 ;
219224
225+ free_mutex :
226+ pthread_mutex_destroy (& (fc -> lock ));
220227free_aggregate_vector :
221228 aggregate_vector_destroy (& (fc -> aggregate_vector ));
222229free_feature_vector :
@@ -227,6 +234,62 @@ int vmaf_feature_collector_init(VmafFeatureCollector **const feature_collector)
227234 return - ENOMEM ;
228235}
229236
237+ int vmaf_feature_collector_mount_model (VmafFeatureCollector * feature_collector ,
238+ VmafModel * model )
239+ {
240+ if (!feature_collector ) return - EINVAL ;
241+ if (!model ) return - EINVAL ;
242+
243+ VmafPredictModel * m = malloc (sizeof (VmafPredictModel ));
244+ if (!m ) return - ENOMEM ;
245+ m -> model = model ;
246+ m -> next = NULL ;
247+
248+ VmafPredictModel * * head = & feature_collector -> models ;
249+ while (* head && (* head )-> next != NULL )
250+ * head = (* head )-> next ;
251+
252+ if (!(* head ))
253+ * head = m ;
254+ else
255+ (* head )-> next = m ;
256+
257+ return 0 ;
258+ }
259+
260+ int vmaf_feature_collector_unmount_model (VmafFeatureCollector * feature_collector ,
261+ VmafModel * model )
262+ {
263+ if (!feature_collector ) return - EINVAL ;
264+ if (!model ) return - EINVAL ;
265+
266+ VmafPredictModel * * head = & feature_collector -> models ;
267+ while (* head && (* head )-> model != model )
268+ head = & (* head )-> next ;
269+
270+ if (!(* head )) return - EINVAL ;
271+
272+ VmafPredictModel * m = * head ;
273+ * head = m -> next ;
274+ free (m );
275+
276+ return 0 ;
277+ }
278+
279+ int vmaf_feature_collector_register_metadata (VmafFeatureCollector * feature_collector ,
280+ VmafMetadataConfiguration metadata_cfg )
281+ {
282+ if (!feature_collector ) return - EINVAL ;
283+ if (!metadata_cfg .feature_name ) return - EINVAL ;
284+ if (!metadata_cfg .callback ) return - EINVAL ;
285+
286+ VmafCallbackList * metadata = feature_collector -> metadata ;
287+ int err = vmaf_metadata_append (metadata , metadata_cfg );
288+ if (err ) return err ;
289+
290+ return 0 ;
291+ }
292+
230293static FeatureVector * find_feature_vector (VmafFeatureCollector * fc ,
231294 const char * feature_name )
232295{
@@ -280,6 +343,51 @@ int vmaf_feature_collector_append(VmafFeatureCollector *feature_collector,
280343 }
281344
282345 err = feature_vector_append (feature_vector , picture_index , score );
346+ if (err ) goto unlock ;
347+
348+ int res = 0 ;
349+
350+ VmafCallbackItem * metadata_iter = feature_collector -> metadata ?
351+ feature_collector -> metadata -> head : NULL ;
352+ while (metadata_iter ) {
353+ // Check current feature name is the same as the metadata feature name
354+ if (!strcmp (metadata_iter -> metadata_cfg .feature_name , feature_name )) {
355+
356+ // Call the callback function with the metadata feature name
357+ VmafMetadata data = {
358+ .feature_name = metadata_iter -> metadata_cfg .feature_name ,
359+ .picture_index = picture_index ,
360+ .score = score ,
361+ };
362+ metadata_iter -> metadata_cfg .callback (metadata_iter -> metadata_cfg .data , & data );
363+ // Move to the next metadata
364+ goto next_metadata ;
365+ }
366+
367+ VmafPredictModel * model_iter = feature_collector -> models ;
368+
369+ // If metadata feature name is not the same as the current feature feature_name
370+ // Check if metadata feature name is the predicted feature
371+ while (model_iter ) {
372+ VmafModel * model = model_iter -> model ;
373+
374+ pthread_mutex_unlock (& (feature_collector -> lock ));
375+ res = vmaf_feature_collector_get_score (feature_collector ,
376+ model -> name , & score , picture_index );
377+ pthread_mutex_lock (& (feature_collector -> lock ));
378+
379+ if (res ) {
380+ pthread_mutex_unlock (& (feature_collector -> lock ));
381+ res |= vmaf_predict_score_at_index (model , feature_collector ,
382+ picture_index , & score , true, true, 0 );
383+ pthread_mutex_lock (& (feature_collector -> lock ));
384+ }
385+ model_iter = model_iter -> next ;
386+ }
387+
388+ next_metadata :
389+ metadata_iter = metadata_iter -> next ;
390+ }
283391
284392unlock :
285393 feature_collector -> timer .end = clock ();
@@ -338,6 +446,10 @@ void vmaf_feature_collector_destroy(VmafFeatureCollector *feature_collector)
338446 aggregate_vector_destroy (& (feature_collector -> aggregate_vector ));
339447 for (unsigned i = 0 ; i < feature_collector -> cnt ; i ++ )
340448 feature_vector_destroy (feature_collector -> feature_vector [i ]);
449+ while (feature_collector -> models )
450+ vmaf_feature_collector_unmount_model (feature_collector ,
451+ feature_collector -> models -> model );
452+ vmaf_metadata_destroy (feature_collector -> metadata );
341453 free (feature_collector -> feature_vector );
342454 pthread_mutex_unlock (& (feature_collector -> lock ));
343455 pthread_mutex_destroy (& (feature_collector -> lock ));
0 commit comments