@@ -90,7 +90,8 @@ typedef struct VmafContext {
9090 } pic_params ;
9191 unsigned pic_cnt ;
9292 bool flushed ;
93- VmafPicture prev_ref ; // previous ref pic for PREV_REF extractors (in-order only)
93+ VmafPicture prev_ref ; // n-1 ref pic for PREV_REF extractors (in-order only)
94+ VmafPicture prev_prev_ref ; // n-2 ref pic for PREV_REF extractors (in-order only)
9495} VmafContext ;
9596
9697#ifdef VMAF_BATCH_THREADING
@@ -299,8 +300,7 @@ static int check_picture_pool(VmafContext *vmaf)
299300 if (!vmaf -> thread_pool ) return 0 ;
300301 if (vmaf -> picture_pool ) return 0 ;
301302
302- // Default to 2x thread count if not explicitly preallocated
303- const unsigned pic_cnt = vmaf -> cfg .n_threads * 2 ;
303+ const unsigned pic_cnt = vmaf -> cfg .n_threads * 2 + 2 ;
304304
305305 int err = prepare_picture_pool (vmaf , pic_cnt ,
306306 vmaf -> pic_params .w ,
@@ -351,6 +351,8 @@ int vmaf_close(VmafContext *vmaf)
351351 vmaf_thread_pool_wait (vmaf -> thread_pool );
352352 if (vmaf -> prev_ref .ref )
353353 vmaf_picture_unref (& vmaf -> prev_ref );
354+ if (vmaf -> prev_prev_ref .ref )
355+ vmaf_picture_unref (& vmaf -> prev_prev_ref );
354356 vmaf_framesync_destroy (vmaf -> framesync );
355357 feature_extractor_vector_destroy (& (vmaf -> registered_feature_extractors ));
356358 vmaf_feature_collector_destroy (vmaf -> feature_collector );
@@ -486,7 +488,7 @@ int vmaf_use_features_from_model_collection(VmafContext *vmaf,
486488
487489struct ThreadData {
488490 VmafFeatureExtractorContext * fex_ctx ;
489- VmafPicture ref , dist , prev_ref ;
491+ VmafPicture ref , dist , prev_ref , prev_prev_ref ;
490492 unsigned index ;
491493 VmafFeatureCollector * feature_collector ;
492494 VmafFeatureExtractorContextPool * fex_ctx_pool ;
@@ -500,15 +502,21 @@ static void threaded_extract_func(void *e, void **thread_data)
500502
501503 if (f -> prev_ref .ref )
502504 f -> fex_ctx -> fex -> prev_ref = f -> prev_ref ;
505+ if (f -> prev_prev_ref .ref )
506+ f -> fex_ctx -> fex -> prev_prev_ref = f -> prev_prev_ref ;
503507
504508 f -> err = vmaf_feature_extractor_context_extract (f -> fex_ctx , & f -> ref , NULL ,
505509 & f -> dist , NULL , f -> index ,
506510 f -> feature_collector );
507511
508512 if (f -> prev_ref .ref ) {
509- memset ( & f -> fex_ctx -> fex -> prev_ref , 0 , sizeof ( f -> fex_ctx -> fex -> prev_ref )) ;
513+ f -> fex_ctx -> fex -> prev_ref = ( VmafPicture ){ 0 } ;
510514 vmaf_picture_unref (& f -> prev_ref );
511515 }
516+ if (f -> prev_prev_ref .ref ) {
517+ f -> fex_ctx -> fex -> prev_prev_ref = (VmafPicture ){0 };
518+ vmaf_picture_unref (& f -> prev_prev_ref );
519+ }
512520
513521 f -> err = vmaf_fex_ctx_pool_release (f -> fex_ctx_pool , f -> fex_ctx );
514522 vmaf_picture_unref (& f -> ref );
@@ -517,7 +525,7 @@ static void threaded_extract_func(void *e, void **thread_data)
517525
518526#ifdef VMAF_BATCH_THREADING
519527struct ThreadDataBatch {
520- VmafPicture ref , dist , prev_ref ;
528+ VmafPicture ref , dist , prev_ref , prev_prev_ref ;
521529 unsigned index ;
522530 VmafFeatureCollector * feature_collector ;
523531 RegisteredFeatureExtractors * registered_fex ;
@@ -567,6 +575,8 @@ static void threaded_extract_batch_func(void *e, void **thread_data)
567575 if (fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) {
568576 if (f -> prev_ref .ref )
569577 td -> fex_ctx [i ]-> fex -> prev_ref = f -> prev_ref ;
578+ if (f -> prev_prev_ref .ref )
579+ td -> fex_ctx [i ]-> fex -> prev_prev_ref = f -> prev_prev_ref ;
570580 }
571581
572582 int err = vmaf_feature_extractor_context_extract (td -> fex_ctx [i ],
@@ -575,9 +585,10 @@ static void threaded_extract_batch_func(void *e, void **thread_data)
575585 f -> index ,
576586 f -> feature_collector );
577587
578- if (fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF )
579- memset (& td -> fex_ctx [i ]-> fex -> prev_ref , 0 ,
580- sizeof (td -> fex_ctx [i ]-> fex -> prev_ref ));
588+ if (fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) {
589+ td -> fex_ctx [i ]-> fex -> prev_ref = (VmafPicture ){0 };
590+ td -> fex_ctx [i ]-> fex -> prev_prev_ref = (VmafPicture ){0 };
591+ }
581592
582593 if (err ) {
583594 f -> err = err ;
@@ -588,6 +599,8 @@ static void threaded_extract_batch_func(void *e, void **thread_data)
588599unref :
589600 if (f -> prev_ref .ref )
590601 vmaf_picture_unref (& f -> prev_ref );
602+ if (f -> prev_prev_ref .ref )
603+ vmaf_picture_unref (& f -> prev_prev_ref );
591604 vmaf_picture_unref (& f -> ref );
592605 vmaf_picture_unref (& f -> dist );
593606}
@@ -622,21 +635,23 @@ static int threaded_read_pictures(VmafContext *vmaf, VmafPicture *ref,
622635 & fex_ctx );
623636 if (err ) return err ;
624637
625- VmafPicture pic_a , pic_b , prev_ref = { 0 };
638+ VmafPicture pic_a , pic_b , prev_ref = { 0 }, prev_prev_ref = { 0 } ;
626639 vmaf_picture_ref (& pic_a , ref );
627640 vmaf_picture_ref (& pic_b , dist );
628641
629- if ((fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) &&
630- vmaf -> prev_ref .ref )
631- {
632- vmaf_picture_ref (& prev_ref , & vmaf -> prev_ref );
642+ if (fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) {
643+ if (vmaf -> prev_ref .ref )
644+ vmaf_picture_ref (& prev_ref , & vmaf -> prev_ref );
645+ if (vmaf -> prev_prev_ref .ref )
646+ vmaf_picture_ref (& prev_prev_ref , & vmaf -> prev_prev_ref );
633647 }
634648
635649 struct ThreadData data = {
636650 .fex_ctx = fex_ctx ,
637651 .ref = pic_a ,
638652 .dist = pic_b ,
639653 .prev_ref = prev_ref ,
654+ .prev_prev_ref = prev_prev_ref ,
640655 .index = index ,
641656 .feature_collector = vmaf -> feature_collector ,
642657 .fex_ctx_pool = vmaf -> fex_ctx_pool ,
@@ -649,12 +664,17 @@ static int threaded_read_pictures(VmafContext *vmaf, VmafPicture *ref,
649664 vmaf_picture_unref (& pic_a );
650665 vmaf_picture_unref (& pic_b );
651666 if (prev_ref .ref ) vmaf_picture_unref (& prev_ref );
667+ if (prev_prev_ref .ref ) vmaf_picture_unref (& prev_prev_ref );
652668 return err ;
653669 }
654670 }
655671
656- if (vmaf -> prev_ref .ref )
657- vmaf_picture_unref (& vmaf -> prev_ref );
672+ if (vmaf -> prev_prev_ref .ref )
673+ vmaf_picture_unref (& vmaf -> prev_prev_ref );
674+ if (vmaf -> prev_ref .ref ) {
675+ vmaf -> prev_prev_ref = vmaf -> prev_ref ;
676+ vmaf -> prev_ref = (VmafPicture ){0 };
677+ }
658678 vmaf_picture_ref (& vmaf -> prev_ref , ref );
659679
660680 return vmaf_picture_unref (ref ) | vmaf_picture_unref (dist );
@@ -670,17 +690,20 @@ static int threaded_read_pictures_batch(VmafContext *vmaf, VmafPicture *ref,
670690
671691 int err = 0 ;
672692
673- VmafPicture pic_a , pic_b , prev_ref = { 0 };
693+ VmafPicture pic_a , pic_b , prev_ref = { 0 }, prev_prev_ref = { 0 } ;
674694 vmaf_picture_ref (& pic_a , ref );
675695 vmaf_picture_ref (& pic_b , dist );
676696
677697 if (vmaf -> prev_ref .ref )
678698 vmaf_picture_ref (& prev_ref , & vmaf -> prev_ref );
699+ if (vmaf -> prev_prev_ref .ref )
700+ vmaf_picture_ref (& prev_prev_ref , & vmaf -> prev_prev_ref );
679701
680702 struct ThreadDataBatch data = {
681703 .ref = pic_a ,
682704 .dist = pic_b ,
683705 .prev_ref = prev_ref ,
706+ .prev_prev_ref = prev_prev_ref ,
684707 .index = index ,
685708 .feature_collector = vmaf -> feature_collector ,
686709 .registered_fex = & vmaf -> registered_feature_extractors ,
@@ -694,11 +717,16 @@ static int threaded_read_pictures_batch(VmafContext *vmaf, VmafPicture *ref,
694717 vmaf_picture_unref (& pic_a );
695718 vmaf_picture_unref (& pic_b );
696719 if (prev_ref .ref ) vmaf_picture_unref (& prev_ref );
720+ if (prev_prev_ref .ref ) vmaf_picture_unref (& prev_prev_ref );
697721 return err ;
698722 }
699723
700- if (vmaf -> prev_ref .ref )
701- vmaf_picture_unref (& vmaf -> prev_ref );
724+ if (vmaf -> prev_prev_ref .ref )
725+ vmaf_picture_unref (& vmaf -> prev_prev_ref );
726+ if (vmaf -> prev_ref .ref ) {
727+ vmaf -> prev_prev_ref = vmaf -> prev_ref ;
728+ vmaf -> prev_ref = (VmafPicture ){0 };
729+ }
702730 vmaf_picture_ref (& vmaf -> prev_ref , ref );
703731
704732 return vmaf_picture_unref (ref ) | vmaf_picture_unref (dist );
@@ -980,18 +1008,21 @@ int vmaf_read_pictures(VmafContext *vmaf, VmafPicture *ref, VmafPicture *dist,
9801008 & dist_device : & dist_host ;
9811009#endif
9821010
983- if ((fex_ctx -> fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) &&
984- vmaf -> prev_ref .ref )
985- {
986- fex_ctx -> fex -> prev_ref = vmaf -> prev_ref ;
1011+ if (fex_ctx -> fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) {
1012+ if (vmaf -> prev_ref .ref )
1013+ fex_ctx -> fex -> prev_ref = vmaf -> prev_ref ;
1014+ if (vmaf -> prev_prev_ref .ref )
1015+ fex_ctx -> fex -> prev_prev_ref = vmaf -> prev_prev_ref ;
9871016 }
9881017
9891018 err = vmaf_feature_extractor_context_extract (fex_ctx , ref , NULL , dist ,
9901019 NULL , index ,
9911020 vmaf -> feature_collector );
9921021
993- if (fex_ctx -> fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF )
994- memset (& fex_ctx -> fex -> prev_ref , 0 , sizeof (fex_ctx -> fex -> prev_ref ));
1022+ if (fex_ctx -> fex -> flags & VMAF_FEATURE_EXTRACTOR_PREV_REF ) {
1023+ fex_ctx -> fex -> prev_ref = (VmafPicture ){0 };
1024+ fex_ctx -> fex -> prev_prev_ref = (VmafPicture ){0 };
1025+ }
9951026
9961027 if (err ) return err ;
9971028 }
@@ -1011,9 +1042,12 @@ int vmaf_read_pictures(VmafContext *vmaf, VmafPicture *ref, VmafPicture *dist,
10111042#endif
10121043 }
10131044
1014- if (vmaf -> prev_ref .ref )
1015- vmaf_picture_unref (& vmaf -> prev_ref );
1016-
1045+ if (vmaf -> prev_prev_ref .ref )
1046+ vmaf_picture_unref (& vmaf -> prev_prev_ref );
1047+ if (vmaf -> prev_ref .ref ) {
1048+ vmaf -> prev_prev_ref = vmaf -> prev_ref ;
1049+ vmaf -> prev_ref = (VmafPicture ){0 };
1050+ }
10171051 if (ref && ref -> ref )
10181052 vmaf_picture_ref (& vmaf -> prev_ref , ref );
10191053#ifdef HAVE_CUDA
0 commit comments