diff --git a/README.md b/README.md index d64457c..268e4dc 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,9 @@ The *Metadata* function returns all the file or track metadata as key-value pair `BSAudioSource(string source[, int track = -1, int adjustdelay = -1, int threads = 0, bool enable_drefs = False, bool use_absolute_path = False, float drc_scale = 0, int cachemode = 1, string cachepath, int cachesize = 100])` -`BSVideoSource(string source[, int track = -1, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, int cachemode = 1, string cachepath, int cachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number])` +`BSVideoSource(string source[, int track = -1, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, int cachemode = 1, string cachepath, int cachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int variableformat = 0])` -`BSSource(string source[, int atrack = -1, int vtrack = -1, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, int cachemode = 1, string cachepath, int acachesize = 100, int vcachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int adjustdelay = -1, float drc_scale = 0])` +`BSSource(string source[, int atrack = -1, int vtrack = -1, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, int cachemode = 1, string cachepath, int acachesize = 100, int vcachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int variableformat = 0, int adjustdelay = -1, float drc_scale = 0])` `BSSetDebugOutput(bool enable = False)` diff --git a/src/avisynth.cpp b/src/avisynth.cpp index 59404de..2de58a2 100644 --- a/src/avisynth.cpp +++ b/src/avisynth.cpp @@ -74,10 +74,13 @@ class AvisynthVideoSource : public IClip { AvisynthVideoSource(const char *Source, int Track, int AFPSNum, int AFPSDen, bool RFF, int Threads, int SeekPreRoll, bool EnableDrefs, bool UseAbsolutePath, int CacheMode, const char *CachePath, int CacheSize, const char *HWDevice, int ExtraHWFrames, - const char *Timecodes, int StartNumber, IScriptEnvironment *Env) + const char *Timecodes, int StartNumber, int VariableFormat, IScriptEnvironment *Env) : FPSNum(AFPSNum), FPSDen(AFPSDen), RFF(RFF) { try { + if (VariableFormat < 0) + throw BestSourceException("Variable format number must be 0 or greater"); + if (FPSDen < 1) throw BestSourceException("FPS denominator needs to be 1 or greater"); @@ -92,7 +95,9 @@ class AvisynthVideoSource : public IClip { if (StartNumber >= 0) Opts["start_number"] = std::to_string(StartNumber); - V.reset(new BestVideoSource(CreateProbablyUTF8Path(Source), HWDevice ? HWDevice : "", ExtraHWFrames, Track, 0, Threads, CacheMode, CachePath, &Opts)); // fixme, should probably expose the nth format selection mechanism + V.reset(new BestVideoSource(CreateProbablyUTF8Path(Source), HWDevice ? HWDevice : "", ExtraHWFrames, Track, Threads, CacheMode, CachePath, &Opts)); + + V->SelectFormatSet(VariableFormat); const BSVideoProperties &VP = V->GetVideoProperties(); if (VP.VF.ColorFamily == cfGray) { @@ -280,8 +285,9 @@ static AVSValue __cdecl CreateBSVideoSource(AVSValue Args, void *UserData, IScri int ExtraHWFrames = Args[13].AsInt(9); const char *Timecodes = Args[14].AsString(nullptr); int StartNumber = Args[15].AsInt(-1); + int VariableFormat = Args[16].AsInt(0); - return new AvisynthVideoSource(Source, Track, FPSNum, FPSDen, RFF, Threads, SeekPreroll, EnableDrefs, UseAbsolutePath, CacheMode, CachePath, CacheSize, HWDevice, ExtraHWFrames, Timecodes, StartNumber, Env); + return new AvisynthVideoSource(Source, Track, FPSNum, FPSDen, RFF, Threads, SeekPreroll, EnableDrefs, UseAbsolutePath, CacheMode, CachePath, CacheSize, HWDevice, ExtraHWFrames, Timecodes, StartNumber, VariableFormat, Env); } class AvisynthAudioSource : public IClip { @@ -422,9 +428,9 @@ static constexpr auto PopulateArgNames() { return Result; } -static constexpr char BSVideoSourceAvsArgs[] = "[source]s[track]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[cachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i"; +static constexpr char BSVideoSourceAvsArgs[] = "[source]s[track]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[cachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[variableformat]i"; static constexpr char BSAudioSourceAvsArgs[] = "[source]s[track]i[adjustdelay]i[threads]i[enable_drefs]b[use_absolute_path]b[drc_scale]f[cachemode]i[cachepath]s[cachesize]i"; -static constexpr char BSSourceAvsArgs[] = "[source]s[atrack]i[vtrack]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[acachesize]i[vcachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[adjustdelay]i[drc_scale]f"; +static constexpr char BSSourceAvsArgs[] = "[source]s[atrack]i[vtrack]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[acachesize]i[vcachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[variableformat]i[adjustdelay]i[drc_scale]f"; static constexpr std::array BSVArgNames = PopulateArgNames(); static constexpr std::array BSAArgNames = PopulateArgNames(); diff --git a/src/vapoursynth.cpp b/src/vapoursynth.cpp index 0525692..ce64c84 100644 --- a/src/vapoursynth.cpp +++ b/src/vapoursynth.cpp @@ -182,7 +182,7 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC if (ShowProgress) { auto NextUpdate = std::chrono::high_resolution_clock::now(); int LastValue = -1; - D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, VariableFormat, Threads, CacheMode, CachePath ? CachePath : "", &Opts, + D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, Threads, CacheMode, CachePath ? CachePath : "", &Opts, [vsapi, Core, &NextUpdate, &LastValue](int Track, int64_t Cur, int64_t Total) { if (NextUpdate < std::chrono::high_resolution_clock::now()) { if (Total == INT64_MAX && Cur == Total) { @@ -200,10 +200,11 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC })); } else { - D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, VariableFormat, Threads, CacheMode, CachePath ? CachePath : "", &Opts)); + D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, Threads, CacheMode, CachePath ? CachePath : "", &Opts)); } D->V->SelectFormatSet(VariableFormat); + const BSVideoProperties &VP = D->V->GetVideoProperties(); if ((VP.VF.ColorFamily == 0 && VariableFormat != -1) || !vsapi->queryVideoFormat(&D->VI.format, VP.VF.ColorFamily, VP.VF.Float, VP.VF.Bits, VP.VF.SubSamplingW, VP.VF.SubSamplingH, Core)) throw BestSourceException("Unsupported video format from decoder (probably less than 8 bit or palette)"); diff --git a/src/videosource.cpp b/src/videosource.cpp index 3a298a1..3ef9724 100644 --- a/src/videosource.cpp +++ b/src/videosource.cpp @@ -868,8 +868,8 @@ bool BestVideoSource::NearestCommonFrameRate(BSRational &FPS) { return false; } -BestVideoSource::BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int VariableFormat, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map *LAVFOpts, const ProgressFunction &Progress) - : Source(SourceFile), HWDevice(HWDeviceName), ExtraHWFrames(!HWDeviceName.empty() ? ExtraHWFrames : 0), VideoTrack(Track), VariableFormat(VariableFormat), Threads(Threads) { +BestVideoSource::BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map *LAVFOpts, const ProgressFunction &Progress) + : Source(SourceFile), HWDevice(HWDeviceName), ExtraHWFrames(!HWDeviceName.empty() ? ExtraHWFrames : 0), VideoTrack(Track), Threads(Threads) { // Only make file path absolute if it exists to pass through special protocol paths std::error_code ec; if (std::filesystem::exists(SourceFile, ec)) @@ -963,7 +963,7 @@ BestVideoSource::BestVideoSource(const std::filesystem::path &SourceFile, const } InitializeFormatSets(); - SelectFormatSet(VariableFormat); + SelectFormatSet(-1); if (DefaultFormatSet.NumFrames != DefaultFormatSet.NumRFFFrames) VP.FPS = OriginalFPS; // Restore the original FPS since it's generally always correct for files with RFF set diff --git a/src/videosource.h b/src/videosource.h index 190f602..183597d 100644 --- a/src/videosource.h +++ b/src/videosource.h @@ -292,7 +292,7 @@ class BestVideoSource { bool NearestCommonFrameRate(BSRational &FPS); void InitializeFormatSets(); public: - BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int VariableFormat, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map *LAVFOpts, const ProgressFunction &Progress = nullptr); + BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map *LAVFOpts, const ProgressFunction &Progress = nullptr); [[nodiscard]] int GetTrack() const; // Useful when opening nth video track to get the actual number void SetMaxCacheSize(size_t Bytes); /* Default max size is 1GB */ void SetSeekPreRoll(int64_t Frames); /* The number of frames to cache before the position being fast forwarded to */