AkarinVS / vapoursynth-plugin

My experimental VapourSynth plugin: (1) an enhanced LLVM-based std.Expr (aka lexpr), Select, PropExpr, Text and Tmpl. (2) DLISR. (3) DLVFX (4) CAMBI.
GNU Lesser General Public License v3.0
37 stars 8 forks source link
llvm vapoursynth vapoursynth-plugin

Plugin akarin

CAMBI

akarin.Cambi(clip clip[, int window_size = 63, float topk = 0.6, float tvi_threshold = 0.019, bint scores = False, float scaling = 1.0/window_size])

Computes the CAMBI banding score as CAMBI frame property. Unlike VapourSynth-VMAF, this filter is online (no need to batch process the whole video) and provides raw cambi scores (when scores == True).

DLVFX

akarin.DLVFX(clip clip, int op[, float scale=1, float strength=0, int output_depth=clip.format.bits_per_sample, int num_streams=1])

There are three operation modes (official docs):

- op=2: denoising. float strength controls the strength. (Not working.)

Usage Notes:

This filter requires appropriate Video Effects library (v0.6 beta) to be installed. (This library is too large to be bundled with the plugin.) This filter also requires RTX-capable NVidia GPU to run.

DLISR

akarin.DLISR(clip clip, [, int scale=2])

This filter will use Nvidia NGX Technology DLISR DNN to scale up an input clip. Input clip must be in vs.RGBS format. The scale parameter can only be 2/4/8 and note that this filter uses considerable amount of GPU memory (e.g. 2GB for 2x scaling 1080p input)

This filter requires nvngx_dlisr.dll to be present in the same directory as this plugin. This filter requires RTX-capable NVidia GPU to run.

Warning:
Due to peculiar nature of its implementation, this filter only works if it is the only CUDA filter in your script and it will always automatically choose the GPU to use. Please make sure to use CPU versions of other filters if you plan to use DLISR in the script (note that it's fairly computation extensive, so using other GPU filters will likely only slow things down anyway.)

Expr

akarin.Expr(clip[] clips, string[] expr[, int format, int opt=0, int boundary=0])

This works just like std.Expr (esp. with the same SIMD JIT support on x86 hosts), with the following additions:

Select

akarin.Select(clip[] clip_src, clip[] prop_src, string[] expr)

For each frame evaluate the expression expr where clip variables (a-z) references the corresponding frame from prop_src. The result of the evaluation is used as an index to pick a clip from clip_src array which is used to satisfy the current frame request.

It could be used to replace common uses of std.FrameEval where you want to evaluate some metrics and then choose one of the clip to use.

In addition to all operators supported by Expr (except those that access pixel values, which is not possible in Select), Select also has a few extensions:

Also note, unlike Expr, where non-existent frame property will be turned into nan, Select will use 0.0 instead.

As an example, mvsfunc.FilterIf can be implemented like this:

x = mvsfunc.FilterIf(src, flt, '_Combed', prop_clip)             # is equivalent to:
x = core.akarin.Select([src, flt], prop_clip, 'x._Combed 1 0 ?') # when x._Combed is set and True, then pick the 2nd clip (flt)

PropExpr

akarin.PropExpr(clip[] clips, dict=lambda: dict(key=val))

PropExpr is a filter to programmatically compute numeric frame properties. Given a list of clips, it will return the first clip after modifying its frame properties as specified by the dict argument. The expressions have access to the frame property of all the clips.

dict is a Python lambda that returns a Python dict, where each key specifies the expression that evaluates to the new value for the frame property of the same name. The expression supports all operators supported by Select (i.e. no support for pixel access operators.)

For each val, there are three cases:

Additionally, val could be an array, and each output frame will use subsequent element of the array (wrap around to the first).

Some examples:

Note: this peculiar form of specifying the properties is to workaround a limitation of the VS API.

Text

Text is an enhanced text.Text:

akarin.Text(clip[] clips, string format[, int alignment=7, int scale=1, string prop, bint strict=0, bint vspipe=0])

clips are the input clips, the output will come from the first clip. It has the same restrictions are the text.Text filter (YUV/Gray/RGB, 8-16 bit integer or 32-bit float format).

format is a Python f""-style format string. The filter internally uses a slightly modified {fmt}, so please refer to {fmt}'s syntax docs for details. Properties can be specified as in Expr/Select/PropExpr. As a special shorthand, {Prop} is an alias for {x.Prop}. Some simple examples:

The filter supports formatting int/float scalar or arrays, data (shown as string). All the rest are shown as type sepcific placeholders (e.g. <node> for a node).

alignment and scale arguments serve the role as in text.Text.

prop, if set, will make the filter set the specified frame property as the formatted string, and not overlay the string onto the frame.

strict, if set to True, will abort the encoding process if format fails for any frame (due to incorrect format string, but not missing properties.)

vspipe will determine whether to overlay the OSD when the script is run under vspipe. The default False means the OSD will only be visible when the script is run in previewers, not when encoding with vspipe. The check is done by checking the executable name of the current process for "vspipe" (Unix) or "vspipe.exe" (Windows). This setting does not affect prop.

Version

akarin.Version()

Use this function to query the version and features of the plugin. It will return a Python dict with the following keys:

There are two implementations:

  1. The legacy jitasm based one (deprecated, and no longer developed) If you encounter issues and suspect it's related to this JIT, you could set the CPU_LEVEL environment variable to 0/1/2 to force the maximum x86 ISA limit to interpreter/sse2/avx2, respectively. The actual ISA used will be determined based on runtime hardware capabilities and the limit (default to no limit). When reporting issues, please also try limiting the ISA to a lower level (at least try setting CPU_LEVEL to 0 to force using the interpreter) and see the problem still persists.

  2. The new LLVM based implementation (aka lexpr). Features labeled with (*) is only available in this new implementation. If the opt argument is set to 1 (default 0), then it will activate an integer optimization mode, where intermediate values are computed with 32-bit integer for as long as possible. You have to make sure the intermediate value is always representable with int32 to use this optimization (as arithmetics will warp around in this mode.)

Building

To build the plugin, you will need LLVM 10-12 installed (on Windows, you need to build your own) and have llvm-config exectuable in your PATH, then run:

meson build
ninja -C build install

Example LLVM build procedure on windows:

git clone --depth 1 https://github.com/llvm/llvm-project.git --branch release/12.x
cd llvm-project
mkdir build
cd build
cmake -A x64 -Thost=x64 -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_USE_CRT_RELEASE=MT ../llvm
cmake --build --config Release
cmake --install ../install