@@ -682,14 +682,6 @@ class decklink_producer : public IDeckLinkInputCallback
682682 BMDTimeValue in_audio_pts = 0LL ;
683683 core::color_space color_space = core::color_space::bt709;
684684
685- // If the video is delayed too much, audio only will be delivered
686- // we don't want audio only since the buffer is small and we keep avcodec
687- // very busy processing all the (unnecessary) packets. Also, because there is
688- // no audio, the sync values will be incorrect.
689- if (!audio) {
690- return S_OK;
691- }
692-
693685 if (video) {
694686 const auto flags = video->GetFlags ();
695687 has_signal_ = !(flags & bmdFrameHasNoInputSource);
@@ -790,6 +782,25 @@ class decklink_producer : public IDeckLinkInputCallback
790782 }
791783 out_sync_ = out_sync;
792784
785+ // If filter output sync has drifted too far from input sync, recreate the filters to resync.
786+ // This usually happens after signal loss/regain from receiving incomplete frames.
787+ const double frame_duration_threshold = 1.5 / input_format.hz ;
788+ const double sync_drift = std::abs (out_sync - in_sync);
789+ if (sync_drift > frame_duration_threshold) {
790+ CASPAR_LOG (warning) << print () << " Excessive A/V sync drift detected ("
791+ << static_cast <int >(sync_drift * 1000 ) << " ms), recreating filters to resync" ;
792+
793+ // Recreate filters to clear all buffered data
794+ video_filter_ = Filter (vfilter_, AVMEDIA_TYPE_VIDEO, format_desc_, mode_, hdr_);
795+ audio_filter_ = Filter (afilter_, AVMEDIA_TYPE_AUDIO, format_desc_, mode_, hdr_);
796+
797+ in_sync_ = 0.0 ;
798+ out_sync_ = 0.0 ;
799+
800+ // Skip this iteration and start fresh
801+ return S_OK;
802+ }
803+
793804 graph_->set_value (" in-sync" , in_sync * 2.0 + 0.5 );
794805 graph_->set_value (" out-sync" , out_sync * 2.0 + 0.5 );
795806
0 commit comments