github pinterf/AviSynthPlus v3.7.7pre-r5001
Avisynth+ v3.7.7pre-r5001 test build

pre-releaseone hour ago

Avisynth+ v3.7.7pre-r5001 test build

Changes since 3.7.6 (pre 3.7.7)

Full details:
readme_history.txt ·
changelist

Most of the bugs were found by AddressSanitizer (ASan) and UndefinedBehaviorSanitizer (UBSan) builds, or by comparing the output of the different CPU paths, then analysed and fixed with AI tools. Some were reported by users.

New and changed features

  • Overlay, Layer, Subtitle, Text: chroma of subsampled formats uses low-pass filter kernels instead of point samples. top_left on 4:2:0 (3x3), 4:2:2 and 4:4:0: [1 2 1]. 4:1:1 and 4:1:0: [1 2 3 4 3 2 1]/16 (co-sited) and [1 3 5 7 7 5 3 1]/32 (centred) per axis. 4:1:0 left, bottom_left, DV get a new 7x8 kernel, top is centred. Mask edges are clamped. Output changes for these placements.
  • Text and Subtitle: all chroma samples reached by the kernel are drawn, also those beside the chroma blocks of the text.
  • Frame properties: new _Range, numbered by ITU-T H.273 as in VapourSynth: 1 is full, 0 is limited. _ColorRange stays reserved as its older name with 0 and 1 swapped; they are one property, held by the frame as _Range, and plugins and scripts of any version reach it by both names. Key lists give _Range only, propGetAll and propShow both.
  • New AudioStats: audio levels (peak, RMS, clipped samples, loose peak), also per channel, as an array of named values at script load time.
  • AmplifydB: the dB to factor conversion is calculated in double, so AmplifydB(-peak_db) of an AudioStats value gives the exact factor.

Build environment, C API loader, interface

  • Interface version 14.1 (AVISYNTHPLUS_INTERFACE_BUGFIX_VERSION 1), no API change: it marks the _Range / _ColorRange alias. Loader: new has_at_least_v14_1.
  • Linux/macOS: the core exports only the C API (avs_*) and CreateScriptEnvironment / CreateScriptEnvironment2, as the Windows DLL does (about 5000 symbols before). Hidden default symbol visibility, and on ELF platforms also a linker version script generated from avisynth_c.h. Plugins no longer get the core's BitBlt, GetBitmapFont, DrawString*, UnQuote, AVS_linkage etc. substituted for their own copies when a host loads the core with RTLD_GLOBAL.
  • New macro AVS_PLUGIN_EXPORT (avs/capi.h) for plugin entry points: __declspec(dllexport) on Windows, default symbol visibility on POSIX, for plugins built with -fvisibility=hidden. AVSC_EXPORT of C plugins does the same.
  • C API loader moved from the installed headers to the FilterSDK/c_loader samples (source: distrib/). Copy the chosen loader and avisynth_c_loader_common.h into your project. CMake location: share/doc/avisynth/examples/c_loader.
  • New C++17 loader avisynth_c_loader.hpp (avsc::Library) with automatic reference cleanup and API helpers. The C variant targets C11; both share compatibility handling and released-version capability flags.
  • Loader: improved load-error diagnostics (avs_load_library_ex / lib.error()), UTF-8 on Windows, no fixed MAX_PATH buffer.
  • Loader: avs_attach_library / lib.attach() acquires a reference to an already-loaded core. For plugins, avs_bind_plugin_library / lib.bind_plugin() binds without retaining a library reference or requiring cleanup at plugin unload.
  • Loader: new has_frame_props flag (V9+ and all V8/V9 frame property functions present; false on Win32 3.7.1, which is detected as V9, not V8).
  • Loader: host examples and a plugin example covering both C entry points and 64 bit values. Plugin initialization is synchronized with C11/C++ atomics.
  • Loader: fallbacks for selected missing APIs on older cores, including V11 value accessors.
  • Loader: on 3.7.4/3.7.5 (V11, V11.1) functions registered with the same user_data (e.g. NULL) could get mixed up; each one is now registered with its own user_data.
  • Loader: compiles in strict ISO C mode on Linux too (gcc -std=c11).
  • avisynth_c.h: the variadic avs_sprintf is declared __cdecl (new AVSC_API_VARARGS, AVSC_CC_VARARGS). Same ABI and export name as before; fixes a 32 bit clang warning.
  • Fix: GCC build with LTO failed with "inlining failed in call to 'always_inline'" in the SSE4.1 Overlay/Layer mask row preparation (AviSynth#531).
  • Haiku: PROGRAMDIR in AddAutoloadDir is the program's folder (was empty). An unreadable program path gives an empty PROGRAMDIR on any system instead of throwing std::out_of_range.

Fixes: bugs in normal use

  • Non-ASCII file names (non-UTF-8 ANSI code pages):
    • .avsi autoload failed with "Import: couldn't open" (regression since 3.7.6; 3.7.5 crashed) (AviSynth#462).
    • ScriptDir, ScriptName, ScriptFile (and $ScriptDir$ etc.) and StrFromUtf8 were cut short or had garbage at the end on multibyte ANSI code pages and UTF-8 mode (existed since r2487).
    • LoadPlugin and plugin autoload failed with "Cannot load file ... code 126" in a folder with non-ASCII characters, also with utf8=true (regression since 3.7.6). The DLL search directory is restored after loading.
  • WriteFile, WriteFileIf, WriteFileStart, WriteFileEnd on Linux/macOS: a relative name of a not yet existing file ended up in the wrong folder with flush=true. The name is now made absolute as on Windows; an empty, invalid or too long name is an error.
  • Import of a script whose full path is exactly 260 characters, or a UNC path of 260 or more, failed with "couldn't open".
  • aarch64: crash in YUV with alpha to RGB when the bit depth changes (e.g. ConvertToRGB32 from 10-16 bit or float YUVA, ConvertToPlanarRGBA(bits=8)). Since 3.7.6.
  • AVX2 YUV to planar RGB (and RGB to YUV/Y) from 8-16 bit to float: memory overwrite past the end of rows on narrow clips. Since 3.7.6.
  • AVX2 YUV to planar RGB (and RGB to YUV/Y) to 10-14 bit: values above 32767 were not clamped before the final clamp. Since 3.7.6.
  • ConvertToYUV444/ConvertToY (and other planar RGB to YUV/Y) from float RGB to 8-16 bit: output range scaling depended on uninitialized memory. Since 3.7.6.
  • 32 bit float horizontal resize (all resizers), AVX2 and AVX-512: reading past the row end could produce random NaN output pixels. Since 3.7.6.
  • ConvertToXXXX with interlaced=true, 4:2:0 or 4:1:0: heights not giving an integral number of chroma rows per field (e.g. 720x486 to 4:2:0) read outside the source frame. Now an error: height must be mod4, or mod8 with 4:1:0 (existed since AviSynth 2.6) (AviSynthPlus-UT#5).
  • Overlay and Layer, 32 bit float, AVX2, left-sited mask: wrong mask samples for 4:2:2 and 4:2:0. Since 3.7.6.
  • Text and Subtitle(gdi=false) on 4:1:0: misplaced chroma if y was not divisible by 4. Since 3.7.6.
  • Layer(op="Subtract") with YUVA: the blend weight is the original overlay alpha, not the inverted one. Regression since 3.7.6 (r4589).
  • ConvertToYUY2 from sources with alpha (planar RGBA, YUVA, YA) gave "ConvertYV16ToYUY2: Only YV16 is allowed as input"; alpha is now dropped (AviSynth#529).
  • AddAlphaPlane refused greyscale clips; it now gives YA. RemoveAlphaPlane turns YA back into Y (AviSynth#530).
  • Crash at closing a script using Prefetch when its clip is also held in a script variable: worker threads could still run while script functions and filter buffers were freed.
  • Histogram:
    • color2, 10-16 bit limited range, bits below the clip bit depth: U or V at the top of the range was plotted outside the panel. Since 3.7.6.
    • levels, 32 bit float, limited range: luma bars were 16 levels too high and levels above 239 piled up in the last bar. Since 3.7.1.
    • levels on Y+Alpha clips gave an error, now works as on greyscale.
  • Subtitle (gdi=true), 10-16 bit, also RGB: overflow on a bright background; at 16 bit white text edges on white wrapped around to dark pixels.
  • Expr, YA clips: a single expression string was also applied to the alpha plane; alpha is now copied.
  • Expr: x._ColorRange on a clip without this property read as 0 (full), also on YUV. Now it is the format default (RGB 0, others 1). The same for x._Range with its own numbers.

Fixes: accuracy, rounding, limited range levels

Output changes by a rounding step; the values now match ConvertBits and the other paths.

  • Tweak: integer results are rounded on all paths. realcalc=true, chroma at 12-16 bit and chroma from the lookup table without dither truncated; output changes by up to 1.
  • Tweak, 32 bit float: dither was not centred (luma about half an 8 bit step too bright); coring limits and bright used a 256 scale (white 235 became 234.08) (AviSynthPlus-UT#53).
  • Expr cmin, scale_inputs="floatUV", 8-16 bit: half a step too high (17 instead of 16 at 8 bit). Since 3.5.0.
  • Histogram classic, 32 bit float, limited range, bits above 8: bars were not at the same position as at integer bit depths.
  • Histogram "audiolevels": RMS calculated from a mean square rounded down to an integer (-96 dB instead of -92.5 dB near silence); dB values use the AmplifydB formula; full scale shows 0.00dB instead of -0.00dB.
  • Subtitle (gdi=true), 10-16 bit YUV: levels were level * 257 instead of a limited range shift (white Y 60393 instead of 60160 at 16 bit). 32 bit float: chroma off by half an 8 bit step, white in RGB is now 1.0.
  • Limiter, Levels, MaskHS, Expr ymax, cmin, cmax, 32 bit float: limits differed from ConvertBits by a rounding step (e.g. Limiter(show="chroma") marked 16 or 240 as out of range).
  • YToUV without clipY, 32 bit float: grey Y plane was 126/256, now 126/255. Since r2487.
  • Planar YUV <-> RGB conversions to 32 bit float from 8-16 bit are always calculated in float (same as quality=true): limited range white gives exactly 1.0, quality=false and true give the same float output. Not slower.
  • 16 bit planar RGB to YUV/Y with 32 bit float output: limited range RGB to full range output wrapped around above nominal white.

Fixes: same output on every CPU, OS and compiler

  • Expr pow with a negative base, x86 JIT: gave 2.4e38 for powers other than constant 2, 3, 4. Now IEEE 754 like the C paths (-2 ^ 3 is -8, fractional power is NaN); 0 ^ 0.25 is 0.
  • Expr sqrt of a negative number is 0 on all paths (was NaN outside the x86 JIT).
  • Limiter with min > max (degenerate, outside the documented range): the x86 SIMD paths now go to C as well, matching the C and NEON results.
  • Planes left unset (random content from reused frame buffers) are now defined:
    • Expr: an empty expression plane, or alpha without expression, when format changes the bit depth (converted as in ConvertBits).
    • UToY, VToY, Histogram classic/levels/color and YToUV with YUVA clipU and no clipY: alpha is opaque. Histogram color2 alpha is opaque (was 0 in 3.7.6).
  • Format()/propShow shortest number form gave one superfluous digit for a few powers of two (e.g. 2^-24). Since 3.7.6.
  • Planar YUV <-> RGB float C path computes in the same order as SSE2.

Fixes: crash or hang on unusual parameters or input

  • LoadPlugin("") and LoadCPlugin("") terminated the host (uncaught std::filesystem exception); now the usual "Cannot load file" error. Regression since 3.7.6.
  • SegmentedAVISource, SegmentedDirectShowSource: a file name without extension crashed the host; a name longer than 259 characters overflowed a stack buffer; utf8=true did not find non-ASCII names.
  • Video for Windows script open (e.g. VirtualDub): a path whose ANSI form is longer than 259 bytes read past a buffer.
  • PROGRAMDIR in AddAutoloadDir: long paths cut without terminating zero; POSIX current folder restore used FILENAME_MAX instead of PATH_MAX.
  • AviSynth 2.5 plugins and C plugins before interface V11: GetVar, GetVarDef (C: avs_get_var, avs_get_var_try) returned 64 bit long/double unknown to them; now int and float, array elements as well. Since 3.7.4.
  • Animate user_fn: a function which cannot be called with stage crashed the host (also OnCPU, OnCUDA). A non-number, NaN or infinite result is an error. The custom function is not called for the start and end frames, and results are no longer clamped to start..end.
  • Animate: linear integer interpolation is exact (could be one off); frame ranges longer than 2^31 no longer overflow. ApplyRange/Animate without extra arguments: debug assertion.
  • RGBAdjust, ColorYUV analyze=true: stack buffer overflow on huge or NaN-only pixel values; RGBAdjust planar RGB float: crash on NaN pixels.
  • ShowFrameNumber, ShowCRC32: division by zero with scroll=true when size is larger than the clip height; size of 0 or below, NaN or too large never finished, now an error (1..1000000).
  • YToUV accepted clips that do not fit the output frame and wrote past the plane rows; now errors. RGB32/RGB64 as clipA give their alpha plane (AviSynthPlus-UT#8).
  • 8 and 16 bit horizontal resize, AVX-512: some kernels could read up to ~120 bytes past the source buffer on the last row. Since 3.7.6.
  • Histogram "audiolevels": stack overflow with low frame rate, high sample rate or many channels (above about 1 MB audio per frame). Since classic AviSynth.

Fixes: undefined behaviour, NaN parameters

  • Float parameters of built-in filters that are NaN or infinite give an error when the filter uses them. This includes resizers, Bob, param1..3 of ConvertTo..., AddBorders, LetterBox, and (NaN) Tweak, MaskHS, Histogram factor, AddAlphaPlane, ShowSMPTE fps. Too large src_left, src_top, src_width, src_height for the resizer are errors too.
  • Normalize: silent track left as is (was infinite factor/NaN/undefined); 16 bit peak search stopped at the first 32767, missing a later -32768.

Optimizations

  • Text and Subtitle(gdi=false): luma loops skip empty bitmap bytes, chroma visits only set bits. About 20-35% quicker.
  • x86 SSE2 (no SSE4.1): cheaper emulation of unsigned 16 bit min/max (Limiter, Blur/Sharpen, 10-14 bit resizers); fewer instructions in the MSVC SSE2 C resizer pack + clamp.
  • Planar YUV <-> RGB C path (aarch64, no SIMD): int32 exact 16 bit calculation, vectorized by GCC and Clang. Output unchanged.

Don't miss a new AviSynthPlus release

NewReleases is sending notifications on new releases.