diff --git a/aegisub/src/include/aegisub/video_provider.h b/aegisub/src/include/aegisub/video_provider.h index 899e94160..315ea6b64 100644 --- a/aegisub/src/include/aegisub/video_provider.h +++ b/aegisub/src/include/aegisub/video_provider.h @@ -74,8 +74,9 @@ public: // How many frames does this provider wants that Aegisub caches? Set to 0 if it doesn't require caching. virtual int GetDesiredCacheSize() { return 0; } - // For providers that are natively time-based (e.g. DirectShow) - virtual bool IsNativelyByFrames() { return true; } + // For "special" providers that don't deal well with VFR (i.e. Avisynth) + virtual bool NeedsVFRHack() { return false; }; // Returns true if provider needs special VFR treatment + virtual bool IsNativelyByFrames() { return true; }; virtual void OverrideFrameTimeList(Aegisub::IntArray list) {} // Override the list with the provided one, for VFR handling }; diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp index 409c23917..46dd3ce6d 100644 --- a/aegisub/src/video_context.cpp +++ b/aegisub/src/video_context.cpp @@ -285,21 +285,23 @@ void VideoContext::SetVideo(const wxString &filename) { else { keyFramesLoaded = false; } - - bool isVfr = provider->IsVFR(); // Set frame rate fps = provider->GetFPS(); - // if the source is vfr and the provider isn't frame-based (i.e. is dshow), - // we need to jump through some hoops to make VFR work properly. - if (!provider->IsNativelyByFrames() && isVfr) { - FrameRate temp = provider->GetTrueFrameRate(); - provider->OverrideFrameTimeList(temp.GetFrameTimeList()); - } - // source not VFR? set as CFR - else if (!isVfr) { - VFR_Input.SetCFR(fps); - if (VFR_Output.GetFrameRateType() != VFR) VFR_Output.SetCFR(fps); + // does this provider need special vfr treatment? + if (provider->NeedsVFRHack()) { + // FIXME: + // Unfortunately, this hack does not actually work for the one + // provider that needs it (Avisynth). Go figure. + bool isVfr = provider->IsVFR(); + if (!isVfr || provider->IsNativelyByFrames()) { + VFR_Input.SetCFR(fps); + if (VFR_Output.GetFrameRateType() != VFR) VFR_Output.SetCFR(fps); + } + else { + FrameRate temp = provider->GetTrueFrameRate(); + provider->OverrideFrameTimeList(temp.GetFrameTimeList()); + } } // Gather video parameters diff --git a/aegisub/src/video_provider_avs.h b/aegisub/src/video_provider_avs.h index 0ef4a6d0a..986380136 100644 --- a/aegisub/src/video_provider_avs.h +++ b/aegisub/src/video_provider_avs.h @@ -89,6 +89,7 @@ public: void OverrideFrameTimeList(wxArrayInt list); bool IsNativelyByFrames() { return byFrame; } + bool NeedsVFRHack() { return true; } Aegisub::String GetWarning(); Aegisub::String GetDecoderName() { return Aegisub::String(L"Avisynth/") + decoderName; } }; diff --git a/aegisub/src/video_provider_cache.cpp b/aegisub/src/video_provider_cache.cpp index ca6ed778a..f8448c05d 100644 --- a/aegisub/src/video_provider_cache.cpp +++ b/aegisub/src/video_provider_cache.cpp @@ -179,6 +179,9 @@ void VideoProviderCache::OverrideFrameTimeList(Aegisub::IntArray list) { bool VideoProviderCache::IsNativelyByFrames() { return master->IsNativelyByFrames(); } +bool VideoProviderCache::NeedsVFRHack() { + return master->NeedsVFRHack(); +} Aegisub::String VideoProviderCache::GetWarning() { return master->GetWarning(); } diff --git a/aegisub/src/video_provider_cache.h b/aegisub/src/video_provider_cache.h index d2bda6339..606b2196d 100644 --- a/aegisub/src/video_provider_cache.h +++ b/aegisub/src/video_provider_cache.h @@ -90,6 +90,7 @@ public: virtual FrameRate GetTrueFrameRate(); virtual void OverrideFrameTimeList(Aegisub::IntArray list); // Override the list with the provided one, for VFR handling virtual bool IsNativelyByFrames(); + virtual bool NeedsVFRHack(); virtual Aegisub::String GetWarning(); virtual Aegisub::String GetDecoderName(); }; diff --git a/aegisub/src/video_provider_dshow.h b/aegisub/src/video_provider_dshow.h index 2cdd09c8f..44a50d498 100644 --- a/aegisub/src/video_provider_dshow.h +++ b/aegisub/src/video_provider_dshow.h @@ -125,6 +125,7 @@ public: Aegisub::String GetDecoderName() { return L"DirectShow"; } bool IsNativelyByFrames() { return false; } + bool NeedsVFRHack() { return true; } void OverrideFrameTimeList(Aegisub::IntArray list); int GetDesiredCacheSize() { return 8; } diff --git a/aegisub/src/video_provider_ffmpegsource.h b/aegisub/src/video_provider_ffmpegsource.h index a568e2877..9af09b4f9 100644 --- a/aegisub/src/video_provider_ffmpegsource.h +++ b/aegisub/src/video_provider_ffmpegsource.h @@ -87,7 +87,6 @@ public: bool IsVFR() { return true; }; FrameRate GetTrueFrameRate() { return Timecodes; }; Aegisub::String GetDecoderName() { return L"FFmpegSource"; } - bool IsNativelyByFrames() { return true; } int GetDesiredCacheSize() { return 8; } };