View Full Version : AviSynth+ thread Vol.2
hello_hello
18th December 2024, 15:17
This is what AvsPmod displays. Same video each time.
https://imgur.com/FSCD8jg.png
https://imgur.com/JSyb1rR.png
Jamaika
18th December 2024, 15:29
Thanks for the info. That means a crappy ffmpeg plugin.
pinterf
18th December 2024, 15:38
Thanks for the info. That means a crappy ffmpeg plugin.
Also, older Avisynth plugins (technically: which are using NewVideoFrame and not MakeWritable/NewVideoFrame2 for the new frame creation) are not able to pass input frame properties.
wonkey_monkey
8th January 2025, 00:56
What exactly does VideoInfo::FramesFromAudioSamples return? The documentation isn't very specific - is it strictly the minimum number of frames that would cover that number of audio samples?
E.g. if you have 25fps video and 48000Hz audio, would FramesFromAudioSamples(48000) return 25 and FramesFromAudioSamples(48001) return 26?
StainlessS
8th January 2025, 09:19
From Avisynth.h [v2.58, (VERSION 3)], baked in header.
// useful functions of the above
bool HasVideo() const { return (width!=0); }
bool HasAudio() const { return (audio_samples_per_second!=0); }
bool IsRGB() const { return !!(pixel_type&CS_BGR); }
bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties
bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; }
bool IsYUV() const { return !!(pixel_type&CS_YUV ); }
bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; }
bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); }
bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); }
bool Is(int property) const { return ((pixel_type & property)==property ); }
bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); }
bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); }
bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); }
bool IsBFF() const { return !!(image_type & IT_BFF); }
bool IsTFF() const { return !!(image_type & IT_TFF); }
bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this
int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes
int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images
int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); }
__int64 AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; }
int FramesFromAudioSamples(__int64 samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * (__int64)fps_numerator)/((__int64)fps_denominator * (__int64)audio_samples_per_second)) : 0; }
__int64 AudioSamplesFromBytes(__int64 bytes) const { return HasAudio() ? bytes / BytesPerAudioSample() : 0; }
__int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); }
int AudioChannels() const { return HasAudio() ? nchannels : 0; }
int SampleType() const{ return sample_type;}
bool IsSampleType(int testtype) const{ return !!(sample_type&testtype);}
int SamplesPerSecond() const { return audio_samples_per_second; }
int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();}
void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; }
void Set(int property) { image_type|=property; }
void Clear(int property) { image_type&=~property; }
I actually got this from Avisynth_v2.6-FINAL_English_Manual,
https://forum.doom9.org/showthread.php?t=152781&highlight=avisynth+v2.6+final+english
direct link here:- https://www.mediafire.com/file/62mphc846sdh6u0/AvisynthEngHelp%252BSDK26_FINAL-2015-05-31.zip/file
You can access avisynth v2.6 header + 2.58, + avisynth_c.h via the List Of Source Files table, FilterSDK\Include whotsit.
pinterf
8th January 2025, 09:50
In actual Avisynth+ code this calculation is the same as StainLessS showed in the old headers.
int VideoInfo::FramesFromAudioSamples(int64_t samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * fps_numerator)/((int64_t)fps_denominator * audio_samples_per_second)) : 0; }
"Normalize" is using it for getting the frame number where the peak audio sample value was found:
frameno = vi.FramesFromAudioSamples(peaksampleno / vi.AudioChannels());
wonkey_monkey
8th January 2025, 10:55
Edit: thinking it over.
So, rather than being a count of frames associated with a count of samples, it is the 0-indexed number of the individual frame which is associated with a sample.
For example (again with a 25fps 48000Hz clip), FramesFromAudioSamples(47999) would return 24, meaning the 25th frame (0-indexed).
However if you needed to know how many frames were needed to contain 47999 samples, that number would be 25 (0-24).
Similarly FramesFromAudioSamples(48000) would return 25 (meaning 26th frame).
I think this might be a distinction worth documenting, as the function name is a bit misleading (I would have removed the plurals and called it FrameFromAudioSample - "Frames" implies it is returning a count).
wonkey_monkey
9th January 2025, 00:03
Bug? If you call env->Invoke from inside your filter, but get the parameters wrong, Avisynth returns an error about invalid arguments, but naming your filter rather than the filter you were trying to invoke.
E.g.:
SpliceFadeIn::SpliceFadeIn(PClip _child, IScriptEnvironment* env) : GenericSpliceFilter(_child, env) {
{
AVSValue args[2] = { child, "32" }; // second parameter should be an integer, not a string
child = env->Invoke("ConvertBits", AVSValue(args, 2)).AsClip();
vi = child->GetVideoInfo();
}
results in the following error:
https://i.imgur.com/g6Sn0oF.png
jpsdr
11th January 2025, 13:49
I've build very recently avisynth, and two plugins DLL disapeared (or were not build) ImageSeq & TimeStretch compared to the previous build i've made.
Is it normal ?
Does it mean that these are not necessary anymore and can be removed from the plugins+/plugins64+ directory, or should i keep the DLL from previous build ?
FranceBB
11th January 2025, 14:41
I think that there have been some changes made by Stephen on DevIL (https://github.com/AviSynth/AviSynthPlus/commit/4a938215f3403fb8dbf766c5c34973eda936a73f) and SoundTouch (https://github.com/AviSynth/AviSynthPlus/commit/28749857b4c446420878f4f10f1ede6cdc5ad4fb) as he removed both dependencies from the Avisynth project.
ImageSeq and TimeStretch() are still there and they're very much needed, but for instance if you open https://github.com/AviSynth/AviSynthPlus/tree/master/plugins/TimeStretch you're only gonna see TimeStretch.cpp without the SoundTouch subfolder.
The same goes for ImageSeq https://github.com/AviSynth/AviSynthPlus/tree/master/plugins/ImageSeq
There's now a new CMakeLists.txt that is supposed to fetch the dependencies from the system rather than from the two subfolders in the Avisynth repository.
By the way, compiling using a new version of SoundTouch is something I really look forward to 'cause Avisynth 3.7.4 will finally have support for up to 32ch in TimeStretch() and I won't have to divide the various audio tracks any longer. :D
jpsdr
11th January 2025, 15:53
So, it means that i have no idea of what to do to have these DLL built again.... :(
It means i have to install some other stuff...???
What ? How ?
FranceBB
11th January 2025, 21:35
I think the best person to ask is Stephen directly (I mean qyot27).
Hopefully he's gonna reply here as he regularly reads.
This is what he wrote in the commit:
ImageSeq: rely on CMake-internal find_package on all platforms
CMake's find_package was already used on everything other than
Windows, but as it turns out, on Windows, the user only needs
to pass -DCMAKE_PREFIX_PATH with the root directory of where
the DevIL installation is for it to find it.
The DevIL SDK as distributed from upstream requires either:
A) Moving the relevant x64 or x86 version of DevIL.lib and ILU.lib
into the main lib/ directory instead of them residing in
lib/{x64,x86}/Release or lib/{x64,x86}/unicode/Release
or
B) Using -DIL_LIBRARIES and -DILU_LIBRARIES when configuring
AviSynth+ to point directly at DevIL.lib and ILU.lib.
This also allows for linking against a static build of DevIL,
removing the need for any extra system DLLs.
wonkey_monkey
11th January 2025, 23:42
I just spent some time being confused over the following:
ColorBars(pixel_type="yv24").ConvertToRGB.ConvertToYV24
My expectation was that colour values would remain the same before and after the two conversions (to within the limits of 8-bit values), but in fact they did differ quite a bit. This seems to be because ColorBars gives itself a _Matrix property of "BT.709" - ConvertToRGB uses that property to do its conversion, but then overwrites it to "RGB", such that the conversion back to YV24 defaults to Rec601.
Anyway, just another of my wacky little observations that had me wondering if there might not be a more "least surprise" way of doing things.
wonkey_monkey
12th January 2025, 02:04
Me again...
I'm getting either an Access Violation exception (if my DLL is built as Release) or just the silent death of VirtualdDub (if built as Debug) when calling AddFunction with an invalid parameter string, e.g.:
env->AddFunction("_", "[fade_length]f[fade_offset]f[fade_offset_type]f!", Create_params, 0); // ! at end of string
env->AddFunction("_", "[fade_length]f[fade_offset]!f[fade_offset_type]", Create_params, 0); // ! in middle of string
env->AddFunction("_", "[fade_length]f[fade_offset]f[fade_offset_type]", Create_params, 0); // missing the final parameter type specifier
AddFunction calls IsValidParameterString, which seems to work correctly in isolation (all of the above return false). A false result should throw an Avisynth exception:
void PluginManager::AddFunction(const char* name, const char* params, IScriptEnvironment::ApplyFunc apply, void* user_data, const char *exportVar, bool isAvs25)
{
if (!IsValidParameterString(params))
Env->ThrowError("%s has an invalid parameter string (bug in filter)", name);
But for some reason it doesn't seem to work. I'm a bit stuck on debugging it any further.
----------------------------------------------------------------------------------
An aside: IsValidParameterString and its attendent functions seem a bit unwieldy; can I suggest the following regex instead? I'm pretty sure it's correct, and it also validates parameter names:
^((\[[A-Za-z_]\w*\])?[.cisbfna][+*]?)*$
In PluginManager.cpp:
...
#define _REGEX_MAX_STACK_COUNT 20000 // needs increasing for long parameter strings
#include <regex>
void PluginManager::AddFunction(const char* name, const char* params, IScriptEnvironment::ApplyFunc apply, void* user_data, const char* exportVar, bool isAvs25)
{
if (!std::regex_match(params, std::regex(R"(^((\[[A-Za-z_]\w*\])?[.cisbfna][+*]?)*$)")))
Env->ThrowError("%s has an invalid parameter string (bug in filter)", name);
...
Selur
12th January 2025, 06:03
btw. is there an eta. for a new official Avisynth release over at https://github.com/AviSynth/AviSynthPlus ?
StainlessS
12th January 2025, 13:22
I'm getting either an Access Violation exception (if my DLL is built as Release) or just the silent death of VirtualdDub (if built as Debug) when calling AddFunction with an invalid parameter string, e.g.:
I think that has been the case for a long time, any screwup in AddFunction can cause weird probs.
FranceBB
12th January 2025, 15:24
btw. is there an eta. for a new official Avisynth release over at https://github.com/AviSynth/AviSynthPlus ?
+1
I would also like to know when 3.7.4 is gonna be released as I really look forward to it. :D
By the way, I was wrong in my prediction here:
between March 18, 2022 and July 16, 2023, 485 days passed, so if we apply the same logic we can expect the future release to be:
AviSynth+ 3.7.4 - Nov 12, 2024
We're currently 61 days after the date I predicted by looking at the time it passed between the other releases.
Avisynth 3.7.3 is 546 days old.
wonkey_monkey
12th January 2025, 17:23
I think that has been the case for a long time, any screwup in AddFunction can cause weird probs.
PluginManager::AutoloadPlugins calls LoadPlugin, which calls TryAsAvs26, which calls AvisynthPluginInit3, which calls AddFunction, which (because of the badly-formatted string) throws an exception back up to TryAsAvs26, which only stores the exception in a string and returns to LoadPlugin, which then ignores the error because it was called with onErrorThrow = false.
I don't know what's ultimately causing the later Access Violation, but changing line 695 of PluginManager.cpp from
LoadPlugin(p, false, &dummy);
to
LoadPlugin(p, true, &dummy);
results in the proper plugin loading exception being thrown and being displayed to the user. I'm not sure why it defaults to being silent but it's been that way for years.
Jamaika
12th January 2025, 18:37
I just spent some time being confused over the following:
ColorBars(pixel_type="yv24").ConvertToRGB.ConvertToYV24
My expectation was that colour values would remain the same before and after the two conversions (to within the limits of 8-bit values), but in fact they did differ quite a bit. This seems to be because ColorBars gives itself a _Matrix property of "BT.709" - ConvertToRGB uses that property to do its conversion, but then overwrites it to "RGB", such that the conversion back to YV24 defaults to Rec601.
Anyway, just another of my wacky little observations that had me wondering if there might not be a more "least surprise" way of doing things.
I have color matrix smpte170m and color range tv.
Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p(tv, smpte170m/unknown/unknown), 640x480, 29.97 fps, 29.97 tbr, 29.97 tbn
The transfer function defined for SMPTE 170M is the same as the one defined in Rec. 709.
pinterf
13th January 2025, 09:48
So, it means that i have no idea of what to do to have these DLL built again.... :(
It means i have to install some other stuff...???
What ? How ?
First, let me mention that there is a quite well maintained page where one can find Avisynth documentation. When we update the 'rst doc' on github then this page is automatically refreshed as well.
https://avisynthplus.readthedocs.io/en/latest/
Specifically about two external DLLs (Soundtouch/Timestretch and DevIL):
https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/contributing/avsplus_external_deps_guide_manual.html
This is a bit more complicated than just "build solution" from Visual Studi and the build process is still under discussions on github, but I succeeded with it (contrary the fact that I always fear of command-line build processes, I like MSVC GUI better :) ). These DLLs are not changed frequently. So if building them is inconvenient you can just copy/leave them from a previous versions. They are still part of Avisynth.
Back to our online documentation.
It's the same as Avisynth wiki. Since we update the documentation on github, only the readthedocs is refreshed. When we don't forget, a short note is put at the beginning of the classic avisynth wiki page about the possibly outdated content. When the changes are small I update the old wiki as well. There are still parts where is Avisynth wiki page is more actual, but I try to convert such sections when I realize the lag.
For example:
http://avisynth.nl/index.php/Subtitle
https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/subtitle.html
Btw, you can follow the actual changes at:
https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/changelist374.html
pinterf
13th January 2025, 10:15
+1
I would also like to know when 3.7.4 is gonna be released as I really look forward to it. :D
By the way, I was wrong in my prediction here:
We're currently 61 days after the date I predicted by looking at the time it passed between the other releases.
Avisynth 3.7.3 is 546 days old.
Yep. Unfortunately, the builds are not restricted to the classic x86/x64 architectures. I cannot provide a release date as it's definitely not a quick process due to the extensive checking required. I don't know how to build the Mac or Arm versions, and all such work is usually done by our build master, qyot27, who is a very thorough person. (And there are still conversations about the build process with ClangCl for example). So it will be released when it's done :)
pinterf
13th January 2025, 10:25
PluginManager::AutoloadPlugins calls LoadPlugin, which calls TryAsAvs26, which calls AvisynthPluginInit3, which calls AddFunction, which (because of the badly-formatted string) throws an exception back up to TryAsAvs26, which only stores the exception in a string and returns to LoadPlugin, which then ignores the error because it was called with onErrorThrow = false.
I don't know what's ultimately causing the later Access Violation, but changing line 695 of PluginManager.cpp from
LoadPlugin(p, false, &dummy);
to
LoadPlugin(p, true, &dummy);
results in the proper plugin loading exception being thrown and being displayed to the user. I'm not sure why it defaults to being silent but it's been that way for years.
When LoadPlugin is called from a .avs script then the error message (exception text) is shown.
Otherwise (called from AutoLoadPlugins) the exception is not shown because there can be other - non Avisynth - helper DLLs in the *.dll list which could prematurely finish the autoloading procedure. I think this is why it is silent in this case.
jpsdr
13th January 2025, 18:35
This is a bit more complicated than just "build solution"...
ARGGH !!!!!! :scared:
I think i'll just keep the previous versions of the DLL for now...
tormento
14th January 2025, 13:39
I think i'll just keep the previous versions of the DLL for now...
I am using the gitlab build since a couple of weeks and it seems ok.
wonkey_monkey
14th January 2025, 15:06
Otherwise (called from AutoLoadPlugins) the exception is not shown because there can be other - non Avisynth - helper DLLs in the *.dll list which could prematurely finish the autoloading procedure. I think this is why it is silent in this case.
Ah yes, that makes complete sense. Still, it would be nice to see the exception if the parameter string is wrong, otherwise us developers are left scratching our heads over an Access Violation (still not sure why that happens, since the plugin shouldn't be pushed to the plugins structure; at one point debugging took me to code for a completely different plugin of mine that I wasn't even compiling at the time), or, if that Access Violation is solved, our plugin silently failing to load.
pinterf
14th January 2025, 15:50
Ah yes, that makes complete sense. Still, it would be nice to see the exception if the parameter string is wrong, otherwise us developers are left scratching our heads over an Access Violation (still not sure why that happens, since the plugin shouldn't be pushed to the plugins structure; at one point debugging took me to code for a completely different plugin of mine that I wasn't even compiling at the time), or, if that Access Violation is solved, our plugin silently failing to load.
I have tried to mess up the parameter string with an extra "!" after the last type.
I was using Avsmeter64 which reports the exception text properly, since it works on the console.
1.) Direct use of LoadPlugin:
LoadPlugin("c:\Github\RemoveDirt\x64\Debug\RemoveDirt.dll")
The console message:
'c:/Github/RemoveDirt/x64/Debug/RemoveDirt.dll' plugin loading error:
RestoreMotionBlocks has an invalid parameter string (bug in filter)
(d:\Tape13\myfolder\s1.avs, line 1)
2.) Then I put the bad DLL to Avisynth's plugins64 folder for autoloading.
Obviously the function with the wrong parameter string did not load at all, so any referencing gave an error on the console output:
Script error: There is no function named 'RestoreMotionBlocks'.
(d:\Tape13\myfolder\s1.avs, line 39)
(d:\Tape13\myfolder\s1.avs, line 13)
wonkey_monkey
14th January 2025, 16:45
Hmm, so no Access Violation. I'll see if I can narrow it down on my computer.
Edit: AVSMeter64.exe aborts in the same manner as GUI programs do. Visual Studio debugging told me "Unhandled exception at 0x00007FFD4C0D36F8 (SubtitleEx_x64.dll) in VirtualDub64.exe: 0xC000001D: Illegal Instruction."
:confused:
I moved SubtitleEx_x64.dll out and this time it showed an access violation in one of my own filters, but also debugging took me to line 25 of FilterConstructor.cpp:
AVSValue retval = Func->apply(funcArgs, Func->user_data,
Func->isAvs25 ? (IScriptEnvironment *)Env25 : Env);
wonkey_monkey
16th January 2025, 19:50
Edit: never mind. Issue is that SuperEq should throw an error if the input audio isn't float, but it doesn't.
pinterf
17th January 2025, 10:25
Edit: never mind. Issue is that SuperEq should throw an error if the input audio isn't float, but it doesn't.
Fixed by qyot27. Was it you who created an issue on this on git?
https://github.com/AviSynth/AviSynthPlus/issues/421
pinterf
17th January 2025, 10:28
Hmm, so no Access Violation. I'll see if I can narrow it down on my computer.
Edit: AVSMeter64.exe aborts in the same manner as GUI programs do. Visual Studio debugging told me "Unhandled exception at 0x00007FFD4C0D36F8 (SubtitleEx_x64.dll) in VirtualDub64.exe: 0xC000001D: Illegal Instruction."
:confused:
I moved SubtitleEx_x64.dll out and this time it showed an access violation in one of my own filters, but also debugging took me to line 25 of FilterConstructor.cpp:
AVSValue retval = Func->apply(funcArgs, Func->user_data,
Func->isAvs25 ? (IScriptEnvironment *)Env25 : Env);
Make sure that this 64 bit dll was created for Avisynth+. 2.5 interface is not compatible.
StainlessS
17th January 2025, 11:58
Fixed by qyot27. Was it you who created an issue on this on git?
https://github.com/AviSynth/AviSynthPlus/issues/421
Issue poster "dartheditous", is Wonkey_Donkey alias on YouTube, so I assume so.
dartheditous@YouTube:- https://www.youtube.com/@DarthEditous/videos
EDIT: A dartheditous favourite:- https://www.youtube.com/watch?v=ZkkUNFXaYyk
EDIT: And source clip transformed by dartheditous to above clip:- https://www.youtube.com/watch?v=dPPjUtiAGYs
EDIT: And conversion script on D9:- https://forum.doom9.org/showthread.php?p=1792366#post1792366
EDIT: A frame from 2nd link clip, converted from 3rd link clip by 4th link script:
https://s20.postimg.cc/xcn153sl9/structures_zpsg2mpn3kn.jpg (https://postimg.cc/image/6et43d7y1/)
wonkey_monkey
17th January 2025, 13:28
What I was most surprised about with that video was how you get realistic shading without even trying, just because of how averaged/anti-aliased pixels stack up around the edges.
Emulgator
17th January 2025, 13:53
Just a quick test if r4096 x64 would finally be able to feed frames to Topaz 2.6.4:
Not. First frame #0, last frame #-1.
All uvz builds I have tested fail in that regard.
3973; 4073 LLVM, 4073 Clang stalls anyway here; 4096 LLVM, Clang both work in AvsPmod)
Last good for me is pinterf's r4066.
wonkey_monkey
17th January 2025, 22:16
I think that has been the case for a long time, any screwup in AddFunction can cause weird probs.
I think I figured this one out. If there are multiple AddFunctions in a plugin's init function, some of them can get added to the AviSynth environment before a faulty one is reached. The faulty one stops the plugin from being properly loaded, but the earlier functions are still created, and calling one of them results in the Access Violation.
pinterf
18th January 2025, 07:30
I think I figured this one out. If there are multiple AddFunctions in a plugin's init function, some of them can get added to the AviSynth environment before a faulty one is reached. The faulty one stops the plugin from being properly loaded, but the earlier functions are still created, and calling one of them results in the Access Violation.
Good catch, now I hope I can reproduce it, so far I tried messing up my first function in the plugin. (And an internal avs function as well, but it didn't give error.)
wonkey_monkey
22nd January 2025, 12:32
This is a vague idea I've had for a while and I'm wondering how practical/useful it might be...
Could GenericVideoFilter be extended, without breaking old filters, to allow communication between filters? I'm thinking of something dead simple like
AVSValue GenericVideoFilter::GetAVSValue(AVSValue input)
which the next filter down could call:
AVSValue result = child->GetAVSValue(val); // val is whatever the "child" (really should be called "parent"...) clip is expecting - array, string, integers representing different instructions
which authors could use to transfer data between filters. The default could be to return false or throw an exception or pass the request up the chain (not really sure how it would work with existing filters). Filters could also pass pointers (either in an array of 32-bit integers, bit clunky, or as a 64-bit integer once Avisynth supports it) so data could then go both down and up the filter chain.
Too esoteric? I rolled my own version with GetAudio and magic numbers before frame properties were implemented and it's been surprisingly useful, but the disadvantage is that clips have to have audio and you can't use certain audio filters. But maybe it's just me who writes such ridiculously complicated filters.
LigH
22nd January 2025, 12:36
Reminds me of TDecimate using hints from TFM, just with an explicit API.
wonkey_monkey
23rd January 2025, 14:49
That's the idea. Something like MVtools wouldn't need separate "super" clips any more; Manalyse could return the original video while also providing access to its motion data through the same clip. A simple helper filter could "dub" clips with other clips' data, and with magic numbers to differentiate (maybe required by the function to help developers avoid clashing with each other), a clip could have multiple sets of data/pointers associated with it.
pinterf
23rd January 2025, 16:07
That's the idea. Something like MVtools wouldn't need separate "super" clips any more; Manalyse could return the original video while also providing access to its motion data through the same clip. A simple helper filter could "dub" clips with other clips' data, and with magic numbers to differentiate (maybe required by the function to help developers avoid clashing with each other), a clip could have multiple sets of data/pointers associated with it.
Why not frame properties?
When mvtools was ported to Vapoursynth it was one of their first step to replace the inter-filter datapointer-in-sound-vi-data hack to frame property usage. I did not yet backported this feature.
Also, in the VapourSynth TIVTC pack the magic-number related things were eliminated as well, I have backported them, if they exists they are used, otherwise the good old magic 32 bits are used for marking the specific properties.
DTL
23rd January 2025, 21:27
That's the idea. Something like MVtools wouldn't need separate "super" clips any more; Manalyse could return the original video while also providing access to its motion data through the same clip. A simple helper filter could "dub" clips with other clips' data, and with magic numbers to differentiate (maybe required by the function to help developers avoid clashing with each other), a clip could have multiple sets of data/pointers associated with it.
Super clip in mvtools is designed for at least 3 needs:
1. Provide padded original frames so that MVs can run slightly out of the frame borders.
2. Provide multi-levels downsized hierarchy of frame copies for hierarchical search algorithm (at least in MAnalyse onCPU but any other filter can use this data).
3. Provide sub-sample shifted copies of frame (sort of upscaled-separated) for sub-sample precision processing (pel > 1). It takes lots of RAM but still faster in comparison with runtime sub-shifting at time of MAnalyse at least.
So you can not simply use pointers to original frames (in most use cases). Only with MAnalyse with DX12-ME feature - it sends full unpadded frames to ME engine and without downsized versions.
Only if you somewhere use MSuper(levels=1, hpad=vpad=0, pel=1) you can make pointers.
DTL
23rd January 2025, 21:40
We got some random crashes at the JincResize plugin (at least in AVS 32bit) - https://forum.doom9.org/showthread.php?t=186053 . It typically happen in SIMD processing functions and looks like out of allocated memory access (0xc___5 code). Mostly happen with production release builds and hard to catch in debugger with debug build.
The SIMD processing functions are 'simple' https://github.com/Asd-g/AviSynth-JincResize/blob/9d813f95e2aee549800e64470ddd6b2841a51c84/src/resize_plane_avx2.cpp#L49 (witout scalar epilogue down to single sample at the end of line) and looks like designed to work only with enough padded lines from AVS core.
The question: Is it known the guaranteed lines padding to work with this design of processing plugins and how it can changed in different AVS (and AVS+) versions ? In the old days of SSE 128bit it can be lower (or not even desigbed to be mod of 128bits) and in the era of AVX-512 it is expected to be at least mod of 512 bit ? The more line padding waste some RAM (and the lower image width - the more RAM wasted relatively).
Also can we got a user-defined control (via some script command) of the frame buffers line padding so it can be some hint to some plugins or user-selection of some balance between RAM usage and performance or some way to increase stability of some plugins with 'unsafe' design of the frame buffer processing functions (but with some more RAM usage if set to too high padding) ?
wonkey_monkey
23rd January 2025, 22:32
Why not frame properties?
Well, mainly because conceptually these things are not per-frame properties (you shouldn't have to get a frame, whether that's frame 0 or any other, to find them), but also because it provides, without cluttering up frame properties, a specific, simple, but very extensible method for reaching back up the filter chain for whatever reason an author might find for doing so.
E.g.: I've written a filter (as part of a suite) that allows you to specify a coordinate on a video, and has use cases where you might add 100 or more such points (each with varying properties). That doesn't seem like it would be a practical or performant use of frame properties to me (but again, maybe I'm the only one who writes such grotesque filters!). Each instance would have to read the existing properties to make sure it appended without overwriting any previous records, for example, which just seems a bit wasteful to me, especially if it's also a non-trivial actual video filter.
Instead, by talking directly to the preceding filter (which can also pass messages further up, if required), I can pass a pointer to a container and get all of those preceding filters to push their data into it. You could also use a filter to modify a preceding filter's behaviour (probably against the ethos of a filter chain, but potentially a useful trick), which you couldn't do with frame properties.
So you can not simply use pointers to original frames (in most use cases).
It wouldn't be a pointer to a frame, it would be a pointer to the filter instance (or just one of its variables) which generated the clip. With that you could access its methods, which might include one that generates and returns the padded, hierarchical data, or what have you (mvtools is maybe not the best example since passing such data as frames does make some sense; but there are other cases where it's not visual data, or isn't even per-frame data).
I dunno, maybe it is a silly idea that few other people would ever have a reason to use. But - if I'm not mistaken - it would be pretty much zero-cost to implement, practically a one-liner like GenericVideoFilter::GetAudio.
Jamaika
24th January 2025, 08:09
I have a question about the ColorBars plugin.
http://avisynth.nl/index.php/ColorBars
string pixel_type = "RGB32"
Set color format of the returned clip.
May be any of the following: "YUY2", "YV12", "YV24" (v2.60), or (default) "RGB32".
AVS+ "RGB32", "RGB64", "YUY2", or any planar RGB, 4:2:0 or 4:4:4 format.
I use ffmpeg with avisynth 3.7.3+.
End result black screen. Is RGB32\64 supported by ffmpeg 64bit?
ColorBars(width=640, height=480, pixel_type="rgb32")
pinterf
24th January 2025, 10:17
We got some random crashes at the JincResize plugin (at least in AVS 32bit) - https://forum.doom9.org/showthread.php?t=186053 . It typically happen in SIMD processing functions and looks like out of allocated memory access (0xc___5 code). Mostly happen with production release builds and hard to catch in debugger with debug build.
The question: Is it known the guaranteed lines padding to work with this design of processing plugins and how it can changed in different AVS (and AVS+) versions ?
Frame and scanline alignment is 64 bytes. So pitch and rowsize is guaranteed to have 64 bytes granularity.
An unaligned simd load can cause C0000005 as well. I loosely follow that topic; try replacing all _mm_load_xxxx / _mm256_load_xxx / _mm512_load _xxx to _mm_loadu versions and check if errors still occur.
DTL
24th January 2025, 15:02
Frame and scanline alignment is 64 bytes. So pitch and rowsize is guaranteed to have 64 bytes granularity.
Can we expect some user-side control via script to increase (change/set) alignment size ? At the AVS+ environment init at least. Also API control for plugins auto-set (if possible ?). 64 byes is ony 1 AVX512 dataword load and for some formats like float32 it takes also not much samples and sometime 128byte or 256bytes loads may make some better performance (at large frame sizes like 4K 8K) or can work as some test if running out or last line happen and crash.
Also 64bytes starte from the first AVS version or some AVS+ and also exist in latest AVS 2.60 ?
Also the second important question - the N-bytes alignment make also line stride integer number of alignment. But last line of buffer also have padding to the N-1 byte allocated and valid or not ?
https://ibb.co/K5WJ8vZ
Image url https://ibb.co/K5WJ8vZ
In this 3 lines frame buf example of the stride of 0x100 - we make allocation of 0x2E0 bytes (like frame 736x3 dec size) with _aligned_malloc(0x2E0, 64) . Will be the addreses up to 0x300-1 valid ? If not - the 64bytes SIMD read of the end of last line can crash ? Also SIMD write can cause memory corruption if even addresses are in same RAM page and valid for read/write.
The description of _aligned_malloc() at https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc?view=msvc-170 do not describe where located the last valid address ?
pinterf
24th January 2025, 15:20
Can we expect some use-side control via script to increase alignment size ? 64 byes is ony 1 AVX512 dataword load and for some formats like float32 it takes also not much samples and sometime 128byte or 256bytes loads may make some better performance (at large frame sizes like 4K 8K) or can work as some test if running out or last line happen and crash.
Also 64bytes starte from the first AVS version or some AVS+ and also exist in latest AVS 2.60 ?
Also the second important question - the N-bytes alignment make also line stride integer number of alignment. But last line of buffer also have padding to the N-1 byte allocated and valid or not ?
https://ibb.co/K5WJ8vZ
Image url https://ibb.co/K5WJ8vZ
In this 3 lines frame buf example of the stride of 0x100 - we make allocation of 0x2E0 bytes (like frame 736x3 dec size) with _aligned_malloc(0x2E0, 64) . Will be the addreses up to 0x300-1 valid ? If not - the 64bytes SIMD read of the end of last line can crash ? Also SIMD write can cause memory corruption if even addresses are in same RAM page and valid for read/write.
64 byte alignment is documented and plugins can rely on that. Even Avisynth core is using that fact. (In a resizer and in Expr?)
Last line is safe. Originally height * aligned row_size is allocated, so it is safe to use full simd at the very end of the last line as well. Note: the last line is safe up to row_size and not pitch size. Pitch can be double of row_size for example after a SeparateFields (https://avisynthplus.readthedocs.io/en/latest/avisynthdoc/corefilters/separatefields.html#separatefields)
Avs 2.6 aligned frame buffers to 16 bytes, but the user had the opportunity to Crop to completely unaligned frame starting point.
So early plugins had to check the pointers all the time. Some history:
https://github.com/pinterf/RgTools/blob/master/RgTools/removegrain.cpp#L952
DTL
24th January 2025, 15:33
64 byte alignment is documented and plugins can rely on that. Even Avisynth core is using that fact. (In a resizer and in Expr?)
Last line is safe. Originally height * aligned row_size is allocated, so it is safe to use full simd at the very end of the last line as well. Note: the last line is safe up to row_size and not pitch size.
Avs 2.6 aligned frame buffers to 16 bytes,
It is nice to have this in documentation so the plugins developers can put to documentation note about minimum required AVS(+) version.
As for _aligned_malloc(size, alignment) WinAPI - I think because the 'alignment' may be very high and API do not knows anything about internal treatment of allocated area - no any safe addresses exist after aligned_address+size ? And user must calculate size to allocate with space for last SIMD read/write size ?
pinterf
24th January 2025, 15:49
It is nice to have this in documentation so the plugins developers can put to documentation note about minimum required AVS(+) version.
As for _aligned_malloc(size, alignment) WinAPI - I think because the 'alignment' may be very high and API do not knows anything about internal treatment of allocated area - no any safe addresses exist after aligned_address+size ? And user must calculate size to allocate with space for last SIMD read/write size ?
Alignment parameter is only for the beginning address. The size can be anything the user want.
DTL
24th January 2025, 15:53
Alignment parameter is only for the beginning address. The size can be anything the user want.
The main question was "Are there any valid/safe to read/write addresses exist after aligned_address+size ?". If the 'alignment' param is unlimited and can be very large like 4MBytes - it is mostly probably no.
Practically some non-crashable addresses may last till the end of typical 4KBytes RAM page after aligned_address+size. But if start address changes - the crash will happen. So it is the way to have random crashes at different runs.
pinterf
24th January 2025, 15:59
The main question was "Are there any valid/safe to read/write addresses exist after aligned_address+size ?". If the 'alignment' param is unlimited and can be very large like 4MBytes - it is mostly probably no.
https://en.cppreference.com/w/c/memory/aligned_alloc
theoretically the size must be multiple of alignment. It may fail - or not.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.