diff --git a/meson.build b/meson.build index be5caac..d5f4cca 100644 --- a/meson.build +++ b/meson.build @@ -53,10 +53,12 @@ if host_machine.cpu_family().startswith('x86') ) endif +avutil_dep = dependency('libavutil', version: '>=59.39.0') + deps = [ + avutil_dep, dependency('libavcodec', version: '>=61.19.0'), dependency('libavformat', version: '>=61.7.0'), - dependency('libavutil', version: '>=59.39.0'), dependency('libxxhash'), ] @@ -100,7 +102,7 @@ if get_option('enable_plugin') endif shared_module('bestsource', plugin_sources, - dependencies: [bestsource_dep, vapoursynth_dep], + dependencies: [bestsource_dep, vapoursynth_dep, avutil_dep.partial_dependency(compile_args: true, includes: true)], gnu_symbol_visibility: 'hidden', install: true, install_dir: vapoursynth_dep.get_variable(pkgconfig: 'libdir') / 'vapoursynth', 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..1382885 100644 --- a/src/synthshared.cpp +++ b/src/synthshared.cpp @@ -21,7 +21,13 @@ #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) { +extern "C" { +#include +} + +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,14 +55,22 @@ 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); - mapSetInt("_DurationNum", DurNum); - mapSetInt("_DurationDen", DurDen); + if (n < VP.NumFrames - 1) { + int64_t NextPTS = VS.GetFrameInfo(n + 1).PTS; + + // Leave _Duration unset when it can't be computed reliably, let callers decide + // whether or how to guess values. + if (Src->PTS != AV_NOPTS_VALUE && NextPTS != AV_NOPTS_VALUE && NextPTS > Src->PTS) { + int64_t DurNum = VP.TimeBase.Num; + int64_t DurDen = VP.TimeBase.Den; + + vsh::muldivRational(&DurNum, &DurDen, NextPTS - Src->PTS, 1); + mapSetInt("_DurationNum", DurNum); + mapSetInt("_DurationDen", DurDen); + } } + // FIXME Use Src->Duration or the track's duration for the last frame? + // These are how you'd compute the last frame's duration, but they're not always accurate. } mapSetInt("TopFieldFirst", TFF); 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); });