diff --git a/src/avisynth.cpp b/src/avisynth.cpp index 64e99d4..3925e21 100644 --- a/src/avisynth.cpp +++ b/src/avisynth.cpp @@ -255,10 +255,9 @@ class AvisynthVideoSource : public IClip { Env->ThrowError("BestVideoSource: %s", e.what()); } - const BSVideoProperties &VP = V->GetVideoProperties(); AVSMap *Props = Env->getFramePropsRW(Dst); - SetSynthFrameProperties(Src, VP, RFF, V->GetFrameIsTFF(n, RFF), + SetSynthFrameProperties(n, Src, *V, RFF, V->GetFrameIsTFF(n, RFF), [Props, Env](const char *Name, int64_t V) { Env->propSetInt(Props, Name, V, 1); }, [Props, Env](const char *Name, double V) { Env->propSetFloat(Props, Name, V, 1); }, [Props, Env](const char *Name, const char *V, int Size, bool Utf8) { Env->propSetData(Props, Name, V, Size, 1); }); diff --git a/src/synthshared.cpp b/src/synthshared.cpp index 852d92a..a4a28a6 100644 --- a/src/synthshared.cpp +++ b/src/synthshared.cpp @@ -21,7 +21,9 @@ #include "synthshared.h" #include "VSHelper4.h" -void SetSynthFrameProperties(const std::unique_ptr &Src, const BSVideoProperties &VP, bool RFF, bool TFF, const std::function &mapSetInt, const std::function &mapSetFloat, const std::function &mapSetData) { +void SetSynthFrameProperties(int n, const std::unique_ptr &Src, const BestVideoSource &VS, bool RFF, bool TFF, const std::function &mapSetInt, const std::function &mapSetFloat, const std::function &mapSetData) { + const BSVideoProperties VP = VS.GetVideoProperties(); + // Set AR variables if (VP.SAR.Num > 0 && VP.SAR.Den > 0) { mapSetInt("_SARNum", VP.SAR.Num); @@ -49,11 +51,19 @@ void SetSynthFrameProperties(const std::unique_ptr &Src, const B mapSetInt("_FieldBased", FieldBased); mapSetInt("RepeatField", Src->RepeatPict); - // FIXME, use PTS difference between frames instead? if (Src->Duration > 0) { int64_t DurNum = VP.TimeBase.Num; int64_t DurDen = VP.TimeBase.Den; - vsh::muldivRational(&DurNum, &DurDen, Src->Duration, 1); + + int64_t Dur = Src->Duration; + if (n < VP.NumFrames - 1) { + Dur = VS.GetFrameInfo(n + 1).PTS - Src->PTS; + } else if (VP.NumFrames >= 2) { + // Assume the last frame has the same duration as the previous one, if the latter exists + Dur = Src->PTS - VS.GetFrameInfo(n - 1).PTS; + } + + vsh::muldivRational(&DurNum, &DurDen, Dur, 1); mapSetInt("_DurationNum", DurNum); mapSetInt("_DurationDen", DurDen); } diff --git a/src/synthshared.h b/src/synthshared.h index 15ac94b..5fc0107 100644 --- a/src/synthshared.h +++ b/src/synthshared.h @@ -26,6 +26,6 @@ #include #include -void SetSynthFrameProperties(const std::unique_ptr &Src, const BSVideoProperties &VP, bool RFF, bool TFF, const std::function &mapSetInt, const std::function &mapSetFloat, const std::function &mapSetData); +void SetSynthFrameProperties(int n, const std::unique_ptr &Src, const BestVideoSource &VS, bool RFF, bool TFF, const std::function &mapSetInt, const std::function &mapSetFloat, const std::function &mapSetData); #endif \ No newline at end of file diff --git a/src/vapoursynth.cpp b/src/vapoursynth.cpp index 6d3fafb..9b8b606 100644 --- a/src/vapoursynth.cpp +++ b/src/vapoursynth.cpp @@ -108,12 +108,11 @@ static const VSFrame *VS_CC BestVideoSourceGetFrame(int n, int ActivationReason, return nullptr; } - const BSVideoProperties &VP = D->V->GetVideoProperties(); VSMap *Props = vsapi->getFramePropertiesRW(Dst); if (AlphaDst) vsapi->mapConsumeFrame(Props, "_Alpha", AlphaDst, maAppend); - SetSynthFrameProperties(Src, VP, D->RFF, D->V->GetFrameIsTFF(n, D->RFF), + SetSynthFrameProperties(n, Src, *D->V, D->RFF, D->V->GetFrameIsTFF(n, D->RFF), [Props, vsapi](const char *Name, int64_t V) { vsapi->mapSetInt(Props, Name, V, maAppend); }, [Props, vsapi](const char *Name, double V) { vsapi->mapSetFloat(Props, Name, V, maAppend); }, [Props, vsapi](const char *Name, const char *V, int Size, bool Utf8) { vsapi->mapSetData(Props, Name, V, Size, Utf8 ? dtUtf8 : dtBinary, maAppend); });