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_lefton 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:0left,bottom_left,DVget a new 7x8 kernel,topis 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._ColorRangestays 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_Rangeonly,propGetAllandpropShowboth. - 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, soAmplifydB(-peak_db)of an AudioStats value gives the exact factor.
Build environment, C API loader, interface
- Interface version 14.1 (
AVISYNTHPLUS_INTERFACE_BUGFIX_VERSION1), no API change: it marks the_Range/_ColorRangealias. Loader: newhas_at_least_v14_1. - Linux/macOS: the core exports only the C API (
avs_*) andCreateScriptEnvironment/CreateScriptEnvironment2, as the Windows DLL does (about 5000 symbols before). Hidden default symbol visibility, and on ELF platforms also a linker version script generated fromavisynth_c.h. Plugins no longer get the core'sBitBlt,GetBitmapFont,DrawString*,UnQuote,AVS_linkageetc. substituted for their own copies when a host loads the core withRTLD_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_EXPORTof C plugins does the same. - C API loader moved from the installed headers to the
FilterSDK/c_loadersamples (source:distrib/). Copy the chosen loader andavisynth_c_loader_common.hinto 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 fixedMAX_PATHbuffer. - 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_propsflag (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 ownuser_data. - Loader: compiles in strict ISO C mode on Linux too (
gcc -std=c11). avisynth_c.h: the variadicavs_sprintfis declared__cdecl(newAVSC_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:
PROGRAMDIRinAddAutoloadDiris the program's folder (was empty). An unreadable program path gives an emptyPROGRAMDIRon any system instead of throwingstd::out_of_range.
Fixes: bugs in normal use
- Non-ASCII file names (non-UTF-8 ANSI code pages):
.avsiautoload failed with "Import: couldn't open" (regression since 3.7.6; 3.7.5 crashed) (AviSynth#462).ScriptDir,ScriptName,ScriptFile(and$ScriptDir$etc.) andStrFromUtf8were cut short or had garbage at the end on multibyte ANSI code pages and UTF-8 mode (existed since r2487).LoadPluginand plugin autoload failed with "Cannot load file ... code 126" in a folder with non-ASCII characters, also withutf8=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.
ConvertToRGB32from 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
ywas 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
Prefetchwhen 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,bitsbelow 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.levelson 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._ColorRangeon a clip without this property read as 0 (full), also on YUV. Now it is the format default (RGB 0, others 1). The same forx._Rangewith 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 withoutdithertruncated; output changes by up to 1. - Tweak, 32 bit float:
ditherwas not centred (luma about half an 8 bit step too bright);coringlimits andbrightused 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,bitsabove 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 theAmplifydBformula; full scale shows0.00dBinstead 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=falseandtruegive 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
powwith a negative base, x86 JIT: gave 2.4e38 for powers other than constant 2, 3, 4. Now IEEE 754 like the C paths (-2 ^ 3is -8, fractional power is NaN);0 ^ 0.25is 0. - Expr
sqrtof 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
formatchanges the bit depth (converted as in ConvertBits). UToY,VToY, Histogramclassic/levels/colorand YToUV with YUVAclipUand noclipY: alpha is opaque. Histogramcolor2alpha is opaque (was 0 in 3.7.6).
- Expr: an empty expression plane, or alpha without expression, when
- 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("")andLoadCPlugin("")terminated the host (uncaughtstd::filesystemexception); 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=truedid 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.
PROGRAMDIRinAddAutoloadDir: long paths cut without terminating zero; POSIX current folder restore usedFILENAME_MAXinstead ofPATH_MAX.- AviSynth 2.5 plugins and C plugins before interface V11:
GetVar,GetVarDef(C:avs_get_var,avs_get_var_try) returned 64 bitlong/doubleunknown to them; nowintandfloat, array elements as well. Since 3.7.4. - Animate
user_fn: a function which cannot be called withstagecrashed the host (alsoOnCPU,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=truewhensizeis larger than the clip height;sizeof 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
clipAgive 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..3ofConvertTo..., AddBorders, LetterBox, and (NaN) Tweak, MaskHS, Histogramfactor, AddAlphaPlane, ShowSMPTEfps. Too largesrc_left,src_top,src_width,src_heightfor 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.