Skip to content

Commit

Permalink
Use PTS differences for _Duration props
Browse files Browse the repository at this point in the history
frame->duration is often just computed from the track-wide frame rate
and hence unreliable.

When the duration cannot be reliably computed from PTS values (like on
the last frame or when frames have NOPTS), leave _Duration unset.
That way, the caller can decide whether or how to guess values if
necessary.
  • Loading branch information
arch1t3cht committed Feb 16, 2025
1 parent eef4d1d commit fa9c691
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 15 deletions.
6 changes: 4 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
]

Expand Down Expand Up @@ -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',
Expand Down
3 changes: 1 addition & 2 deletions src/avisynth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); });
Expand Down
30 changes: 22 additions & 8 deletions src/synthshared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@
#include "synthshared.h"
#include "VSHelper4.h"

void SetSynthFrameProperties(const std::unique_ptr<BestVideoFrame> &Src, const BSVideoProperties &VP, bool RFF, bool TFF, const std::function<void(const char *, int64_t)> &mapSetInt, const std::function<void(const char *, double)> &mapSetFloat, const std::function<void(const char *, const char *, int, bool)> &mapSetData) {
extern "C" {
#include <libavutil/avutil.h>
}

void SetSynthFrameProperties(int n, const std::unique_ptr<BestVideoFrame> &Src, const BestVideoSource &VS, bool RFF, bool TFF, const std::function<void(const char *, int64_t)> &mapSetInt, const std::function<void(const char *, double)> &mapSetFloat, const std::function<void(const char *, const char *, int, bool)> &mapSetData) {
const BSVideoProperties VP = VS.GetVideoProperties();

// Set AR variables
if (VP.SAR.Num > 0 && VP.SAR.Den > 0) {
mapSetInt("_SARNum", VP.SAR.Num);
Expand Down Expand Up @@ -49,14 +55,22 @@ void SetSynthFrameProperties(const std::unique_ptr<BestVideoFrame> &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);
Expand Down
2 changes: 1 addition & 1 deletion src/synthshared.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@
#include <functional>
#include <cstdint>

void SetSynthFrameProperties(const std::unique_ptr<BestVideoFrame> &Src, const BSVideoProperties &VP, bool RFF, bool TFF, const std::function<void(const char *, int64_t)> &mapSetInt, const std::function<void(const char *, double)> &mapSetFloat, const std::function<void(const char *, const char *, int, bool)> &mapSetData);
void SetSynthFrameProperties(int n, const std::unique_ptr<BestVideoFrame> &Src, const BestVideoSource &VS, bool RFF, bool TFF, const std::function<void(const char *, int64_t)> &mapSetInt, const std::function<void(const char *, double)> &mapSetFloat, const std::function<void(const char *, const char *, int, bool)> &mapSetData);

#endif
3 changes: 1 addition & 2 deletions src/vapoursynth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); });
Expand Down

0 comments on commit fa9c691

Please sign in to comment.