From 6c61e27c6136d2b442aafafe1cd97b8857962a1f Mon Sep 17 00:00:00 2001 From: Fredrik Mellbin Date: Thu, 4 Apr 2024 23:42:24 +0200 Subject: [PATCH] Implement sequence starting number --- README.md | 10 ++++++---- src/avisynth.cpp | 17 ++++++++++------- src/vapoursynth.cpp | 7 ++++++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 299b796..8b301c8 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ ninja -C build install `bs.AudioSource(string source[, int track = -1, int adjustdelay = -1, int threads = 0, bint enable_drefs = False, bint use_absolute_path = False, float drc_scale = 0, string cachepath, int cachesize = 100, bint showprogress = True])` -`bs.VideoSource(string source[, int track = -1, bint variableformat = False, int fpsnum = -1, int fpsden = 1, bint rff = False, int threads = 0, int seekpreroll = 20, bint enable_drefs = False, bint use_absolute_path = False, string cachepath = source, int cachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, bint showprogress = True])` +`bs.VideoSource(string source[, int track = -1, bint variableformat = False, int fpsnum = -1, int fpsden = 1, bint rff = False, int threads = 0, int seekpreroll = 20, bint enable_drefs = False, bint use_absolute_path = False, string cachepath = source, int cachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, bint showprogress = True])` `bs.TrackInfo(string source[, bint enable_drefs = False, bint use_absolute_path = False])` @@ -50,9 +50,9 @@ ninja -C build install `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, string cachepath, int cachesize = 100])` -`BSVideoSource(string source[, int track = -1, bint variableformat = False, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, string cachepath = source, int cachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes])` +`BSVideoSource(string source[, int track = -1, bint variableformat = False, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, string cachepath = source, int cachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number])` -`BSSource(string source[, int atrack, int vtrack = -1, bint variableformat = False, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, string cachepath = source, int acachesize = 100, int vcachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int adjustdelay = -1, float drc_scale = 0])` +`BSSource(string source[, int atrack, int vtrack = -1, bint variableformat = False, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, string cachepath = source, int acachesize = 100, int vcachesize = 1000, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int adjustdelay = -1, float drc_scale = 0])` `BSSetDebugOutput(bool enable = False)` @@ -60,7 +60,7 @@ ninja -C build install ## Argument explanation -*source*: The source filename. Note that image sequences also can be opened by using %d or %03d for zero padded numbers. Sequences may start at any number between 0 and 4. +*source*: The source filename. Note that image sequences also can be opened by using %d or %03d for zero padded numbers. Sequences may start at any number between 0 and 4 unless otherwise specified with *start_number*. *track*: Either a positive number starting from 0 specifying the absolute track number or a negative number to select the nth audio or video track. Throws an error on wrong type or no matching track. @@ -94,6 +94,8 @@ ninja -C build install *timecodes*: Writes a timecode v2 file with all frame times to the file if specified. Note that this option can produce EXTREMELY INVALID TIMECODE FILES due to performing no additional processing or check on the timestamps reported by FFmpeg. It is common for transport streams and other containers to have unknown values (shows up as large negative values) and discontinuous timestamps. +*start_number*: The first number of image sequences. + *showprogress*: Print indexing progress as VapourSynth information level log messages. *level*: The log level of the FFmpeg library. By default quiet. See FFmpeg documentation for allowed constants. Mostly useful for debugging purposes. diff --git a/src/avisynth.cpp b/src/avisynth.cpp index 58ff6ff..e40f12e 100644 --- a/src/avisynth.cpp +++ b/src/avisynth.cpp @@ -63,7 +63,7 @@ class AvisynthVideoSource : public IClip { AvisynthVideoSource(const char *SourceFile, int Track, int AFPSNum, int AFPSDen, bool RFF, int Threads, int SeekPreRoll, bool EnableDrefs, bool UseAbsolutePath, const char *CachePath, int CacheSize, const char *HWDevice, int ExtraHWFrames, - const char *Timecodes, IScriptEnvironment *Env) + const char *Timecodes, int StartNumber, IScriptEnvironment *Env) : FPSNum(AFPSNum), FPSDen(AFPSDen), RFF(RFF) { try { @@ -78,6 +78,8 @@ class AvisynthVideoSource : public IClip { Opts["enable_drefs"] = "1"; if (UseAbsolutePath) Opts["use_absolute_path"] = "1"; + if (StartNumber >= 0) + Opts["start_number"] = std::to_string(StartNumber); V.reset(new BestVideoSource(SourceFile, HWDevice ? HWDevice : "", ExtraHWFrames, Track, false, Threads, CachePath, &Opts)); @@ -269,8 +271,9 @@ static AVSValue __cdecl CreateBSVideoSource(AVSValue Args, void *UserData, IScri const char *HWDevice = Args[11].AsString(); int ExtraHWFrames = Args[12].AsInt(9); const char *Timecodes = Args[13].AsString(nullptr); + int StartNumber = Args[12].AsInt(-1); - return new AvisynthVideoSource(Source, Track, FPSNum, FPSDen, RFF, Threads, SeekPreroll, EnableDrefs, UseAbsolutePath, CachePath, CacheSize, HWDevice, ExtraHWFrames, Timecodes, Env); + return new AvisynthVideoSource(Source, Track, FPSNum, FPSDen, RFF, Threads, SeekPreroll, EnableDrefs, UseAbsolutePath, CachePath, CacheSize, HWDevice, ExtraHWFrames, Timecodes, StartNumber, Env); } class AvisynthAudioSource : public IClip { @@ -363,17 +366,17 @@ static AVSValue __cdecl CreateBSAudioSource(AVSValue Args, void *UserData, IScri static AVSValue __cdecl CreateBSSource(AVSValue Args, void *UserData, IScriptEnvironment *Env) { - const char *FFVArgNames[] = { "source", "track", "fpsnum", "fpsden", "rff", "threads", "seekpreroll", "enable_drefs", "use_absolute_path", "cachepath", "cachesize", "hwdevice", "extrahwframes", "timecodes" }; + const char *FFVArgNames[] = { "source", "track", "fpsnum", "fpsden", "rff", "threads", "seekpreroll", "enable_drefs", "use_absolute_path", "cachepath", "cachesize", "hwdevice", "extrahwframes", "timecodes", "start_number" }; const char *FFAArgNames[] = { "source", "track", "adjustdelay", "threads", "enable_drefs", "use_absolute_path", "drc_scale", "cachepath", "cachesize" }; - AVSValue FFVArgs[] = { Args[0], Args[2], Args[3], Args[4], Args[5], Args[6], Args[7], Args[8], Args[9], Args[10], Args[11], Args[13], Args[14], Args[15] }; + AVSValue FFVArgs[] = { Args[0], Args[2], Args[3], Args[4], Args[5], Args[6], Args[7], Args[8], Args[9], Args[10], Args[11], Args[13], Args[14], Args[15], Args[16] }; static_assert((sizeof(FFVArgs) / sizeof(FFVArgs[0])) == (sizeof(FFVArgNames) / sizeof(FFVArgNames[0])), "Arg error"); AVSValue Video = Env->Invoke("BSVideoSource", AVSValue(FFVArgs, sizeof(FFVArgs) / sizeof(FFVArgs[0])), FFVArgNames); bool WithAudio = Args[1].Defined(); if (WithAudio) { - AVSValue FFAArgs[] = { Args[0], Args[1], Args[16], Args[6], Args[8], Args[9], Args[10], Args[11], Args[17] }; + AVSValue FFAArgs[] = { Args[0], Args[1], Args[17], Args[6], Args[8], Args[9], Args[10], Args[11], Args[18] }; static_assert((sizeof(FFAArgs) / sizeof(FFAArgs[0])) == (sizeof(FFAArgNames) / sizeof(FFAArgNames[0])), "Arg error"); AVSValue Audio = Env->Invoke("BSAudioSource", AVSValue(FFAArgs, sizeof(FFAArgs) / sizeof(FFAArgs[0])), FFAArgNames); AVSValue ADArgs[] = { Video, Audio }; @@ -399,9 +402,9 @@ const AVS_Linkage *AVS_linkage = nullptr; extern "C" AVS_EXPORT const char *__stdcall AvisynthPluginInit3(IScriptEnvironment * Env, const AVS_Linkage *const vectors) { AVS_linkage = vectors; - Env->AddFunction("BSVideoSource", "[source]s[track]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachepath]s[cachesize]i[hwdevice]s[extrahwframes]i[timecodes]s", CreateBSVideoSource, nullptr); + Env->AddFunction("BSVideoSource", "[source]s[track]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachepath]s[cachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i", CreateBSVideoSource, nullptr); Env->AddFunction("BSAudioSource", "[source]s[track]i[adjustdelay]i[threads]i[enable_drefs]b[use_absolute_path]b[drc_scale]f[cachepath]s[cachesize]i", CreateBSAudioSource, nullptr); - Env->AddFunction("BSSource", "[source]s[atrack]i[vtrack]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachepath]s[acachesize]i[vcachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[adjustdelay]i[drc_scale]f", CreateBSSource, nullptr); + Env->AddFunction("BSSource", "[source]s[atrack]i[vtrack]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachepath]s[acachesize]i[vcachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[adjustdelay]i[drc_scale]f", CreateBSSource, nullptr); Env->AddFunction("BSSetDebugOutput", "[enable]b", BSSetDebugOutput, nullptr); Env->AddFunction("BSSetFFmpegLogLevel", "[level]i", BSSetFFmpegLogLevel, nullptr); diff --git a/src/vapoursynth.cpp b/src/vapoursynth.cpp index 8227a46..a352fc6 100644 --- a/src/vapoursynth.cpp +++ b/src/vapoursynth.cpp @@ -141,6 +141,9 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC Track = -1; bool VariableFormat = !!vsapi->mapGetInt(In, "variableformat", 0, &err); int Threads = vsapi->mapGetIntSaturated(In, "threads", 0, &err); + int StartNumber = vsapi->mapGetIntSaturated(In, "start_number", 0, &err); + if (err) + StartNumber = -1; bool ShowProgress = !!vsapi->mapGetInt(In, "showprogress", 0, &err); if (err) ShowProgress = true; @@ -152,6 +155,8 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC Opts["enable_drefs"] = "1"; if (vsapi->mapGetInt(In, "use_absolute_path", 0, &err)) Opts["use_absolute_path"] = "1"; + if (StartNumber >= 0) + Opts["start_number"] = std::to_string(StartNumber); BestVideoSourceData *D = new BestVideoSourceData(); @@ -389,7 +394,7 @@ static void VS_CC SetLogLevel(const VSMap *In, VSMap *Out, void *, VSCore *, con VS_EXTERNAL_API(void) VapourSynthPluginInit2(VSPlugin *plugin, const VSPLUGINAPI *vspapi) { vspapi->configPlugin("com.vapoursynth.bestsource", "bs", "Best Source 2", VS_MAKE_VERSION(BEST_SOURCE_VERSION_MAJOR, BEST_SOURCE_VERSION_MINOR), VS_MAKE_VERSION(VAPOURSYNTH_API_MAJOR, 0), 0, plugin); - vspapi->registerFunction("VideoSource", "source:data;track:int:opt;variableformat:int:opt;fpsnum:int:opt;fpsden:int:opt;rff:int:opt;threads:int:opt;seekpreroll:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;cachepath:data:opt;cachesize:int:opt;hwdevice:data:opt;extrahwframes:int:opt;timecodes:data:opt;showprogress:int:opt;", "clip:vnode;", CreateBestVideoSource, nullptr, plugin); + vspapi->registerFunction("VideoSource", "source:data;track:int:opt;variableformat:int:opt;fpsnum:int:opt;fpsden:int:opt;rff:int:opt;threads:int:opt;seekpreroll:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;cachepath:data:opt;cachesize:int:opt;hwdevice:data:opt;extrahwframes:int:opt;timecodes:data:opt;start_number:int:opt;showprogress:int:opt;", "clip:vnode;", CreateBestVideoSource, nullptr, plugin); vspapi->registerFunction("AudioSource", "source:data;track:int:opt;adjustdelay:int:opt;threads:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;drc_scale:float:opt;cachepath:data:opt;cachesize:int:opt;showprogress:int:opt;", "clip:anode;", CreateBestAudioSource, nullptr, plugin); vspapi->registerFunction("TrackInfo", "source:data;enable_drefs:int:opt;use_absolute_path:int:opt;", "mediatype:int;mediatypestr:data;codec:int;codecstr:data;disposition:int;dispositionstr:data;", GetTrackInfo, nullptr, plugin); vspapi->registerFunction("SetDebugOutput", "enable:int;", "", SetDebugOutput, nullptr, plugin);