Log in

View Full Version : Avisynth+


Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [19] 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

chainik_svp
9th March 2015, 10:35
utim
I looked at the date when you originally reported this, and it was in oct.2014

I was building latest git sources back in October. In fact I was interested in x64 MT version at the first place so almost all my tests was about it.
And I'm now looking at those two builds I've made and yeah, x32 and x64 versions are working in different ways.

For 720p video and 10 MT threads: x32 build stays at about 500 MB, and x64 adds +350 MB on each click on the checkbox.

ultim
9th March 2015, 11:34
utim
I looked at the date when you originally reported this, and it was in oct.2014

I was building latest git sources back in October. In fact I was interested in x64 MT version at the first place so almost all my tests was about it.
And I'm now looking at those two builds I've made and yeah, x32 and x64 versions are working in different ways.

For 720p video and 10 MT threads: x32 build stays at about 500 MB, and x64 adds +350 MB on each click on the checkbox.
Ok, my bad. I did my experiemnt with ffdshow on the i386 build. I'll have to repeat it for x64. and I will let you know of the results.

Groucho2004
9th March 2015, 11:41
For 720p video and 10 MT threads: x32 build stays at about 500 MB, and x64 adds +350 MB on each click on the checkbox.
I have not tried ffdshow but loading the IScriptEnvironment, reading some frames, releasing with "DeleteScriptEnvironment()" several consecutive times does not increase the memory usage with the latest AVS+ x64 build.

martin53
9th March 2015, 17:46
Two notable differences are between GScript and Avs+ (http://forum.doom9.org/showthread.php?p=1648026#post1648026):

In Avs+ there is no need to use GScript("...") to encompass GScript-specific code parts.
The "return" statement terminates the whole function (or script).


Third, with original GScript, I think the variable 'last' is not fed through the GScript part, so scripts need to assign all results to explicit variables (maybe it's only roughly like that, I remember I had to fix some scripts bugs of this kind).

Has this been changed in Avs+, too, or is it still same?

Reel.Deel
9th March 2015, 20:33
my question is: where is the documentation of the cited new features? I may be too stupid to find it. After Avisynth+ install, I compared the doc folder trees with BeyondCompare and can only find same docs, or files where AviSynth 2.6 is more up to date (even if Avisynth+ file date is newer!). The folder 'german' should be renamed 'french', or better removed, if it is neither complete nor updated. Also, I found nothing on the homepage (http://avs-plus.net/) and at most hints in this thread.


This morning I started the AviSynth+ wiki page (http://avisynth.nl/index.php/AviSynth%2B) in hopes to document all of the new features, changes, bugs, etc, really anything that can be helpful to end users and programmers looking to contribute to AviSynth+. Right now the page is sloppy but I'm hoping to improve it in the coming days. Anything that you would like to add/clarify just let me know or edit the wiki yourself :).

martin53
9th March 2015, 21:10
i checked the new script. True this one "freezes", more exactly it keeps running forever by never stopping to output. It outputs all functions a-z, then backwards z-a, then again a-z, then z-a, and seems to keep on doing this forever. Judging by this regular output pattern, are you sure it is not a bug in your script? see output here (http://pastebin.com/6svj5tnl).

Edit: After letting it run loooong enough, it actually finished execution! Is it normal to output everyhting a-z-a-z-a a couple of time?

Yes, exactly this was the change to make it 'freeze' more likely.

Saw it freezing once today with 2.6 MT, but can't reproduce. But it has to do with string handling or so, not at all with plugins. I learned that there's no garbage collection in Avisynth, but it looks very similar to a veeerrry slooow one, or desperate tries to allocate memory. It tended to 'freeze' just after the long string containing all function names was emptied by the while loop, though that was not the only situation.

Will report further success.

ultim
9th March 2015, 21:24
utim
I looked at the date when you originally reported this, and it was in oct.2014

I was building latest git sources back in October. In fact I was interested in x64 MT version at the first place so almost all my tests was about it.
And I'm now looking at those two builds I've made and yeah, x32 and x64 versions are working in different ways.

For 720p video and 10 MT threads: x32 build stays at about 500 MB, and x64 adds +350 MB on each click on the checkbox.

Okay, I managed to reproduce it under x64 ffdshow. I am inclined to say however, that since the leak only occurs under ffdshow and only in x64, that ffdshow should be checked first. No leak in x64 avisynth with either avsmeter, virtualdub, or mpc-hc, and also no leak in 32-bit ffdshow. It only happens with x64 ffdshow. Can someone please check the ffdshow sources?

ultim
9th March 2015, 21:26
Yes, exactly this was the change to make it 'freeze' more likely.

Saw it freezing once today with 2.6 MT, but can't reproduce. But it has to do with string handling or so, not at all with plugins. I learned that there's no garbage collection in Avisynth, but it looks very similar to a veeerrry slooow one, or desperate tries to allocate memory. It tended to 'freeze' just after the long string containing all function names was emptied by the while loop, though that was not the only situation.

Will report further success.

Oh my gosh, I bet it has to do something with AviSynth's StringDump. This is only a hunch though. Is it reproducible on classic Avisynth, even if only sporadically?

chainik_svp
9th March 2015, 21:31
ultim

The only question left is how I was able to remove memory leaks with those two patches to AVS+? :)

Just try to believe that cache is not cleaned and prefetcher filter is not deleted ;)

I admit that it isn't so obvious as I was thinking in October BUT memory issues are always so ... unpredictable.

StainlessS
9th March 2015, 21:36
I'll gladly do, just working on it.



Interesting. I always wondered why identical function_parameter lines appeared more than once. If Groucho2004 extended the AVSInfoTool to display the parameter lists, we'd probably know if it's a bug in AviSynth or in RT_Stats. Actually, I re-included a check that prevents similar lines also for internal functions, not only for plugins (updated my post in RT_Stats thread) though I understand it would be better to list the functions with their multiple parameter lists.

I believe this has come up before, I think that only a single parameter list is available outside of Avisynth dll (available internal only) and so AVSInfoTool will likewise be oblivious to the differing arg list. I take it that the same is true of AVS+, (although I seem to remember that some lists in AVS+ have been removed, ie return empty strings).

ultim
9th March 2015, 21:51
ultim

The only question left is how I was able to remove memory leaks with those two patches to AVS+? :)

Just try to believe that cache is not cleaned and prefetcher filter is not deleted ;)

I admit that it isn't so obvious as I was thinking in October BUT memory issues are always so ... unpredictable.

I believe you that cache and prefetcher are not cleaned. I also verified it myself. I'm just saying those not being cleaned is a result of x64 ffdshow doing something different than "normal". At least most probably as things look right now. Like not releasing the clip before the ScriptEnvironment is destroyed, for example, would lead to the exact same leak. Why your patches "solve" this is also pretty clear. They basically inhibit caching, so even if caches are not cleaned up, there is little left to leak. But as you might guess, your patches are not the solution to this problem.

Can someone from you guys please have a look at ffdshow? The main points to watch out for are that
- all clip and frame references are released before the ScriptEnv is destructed,
- that the ScriptEnv is destructed every time the avisynth script is disabled or reloaded, and
- that the latest avs+ header is used for compilation.

The second point is also important to ensure correct script execution, due to plugin loading.

EDIT: Notes on using the correct avisynth header. Avs+'s header is compatible with all previously compiled x64 plugins, even those not compiled for Avs+. So using Avs+'s header makes sure you use the correct one as it is also the latest. The very recent Avisynth 2.6 RC1 introduced modifications to the x64 interface which is NOT compatible to any x64 plugin from before, so until the situation is cleared up, I strongly advice you not to use the Avisynth 2.6 header in 64-bit mode, as it will break any and all 64-bit plugins.

chainik_svp
9th March 2015, 22:24
One "patch" was pretty simple. I have a very dumb way to debug something inside AVS and/or plugins - by placing fprintf.
And I was placed them into both Prefetcher constructor and destructor. And guess what? :)
Well, may be I have to re-check it with the latest sources...

About the cache issue.

The only place where VideoFrame can be born is ScriptEnvironment::GetNewFrame().
And it can't be made with some another vfb (unlike how it's working in Avisynth).
In fact every VideoFrame is always have it's own vfb. So it (VideoFrame) should also destroy it's vfb.

Again: vfb's are NOT shared between video frames.

So your main point about
You cannot delete the vfb every time a VideoFrame is destroyed, because due to subframes, vfbs can be shared among multiple VideoFrames.
doesn't seems to be correct.
Or I'm still missing something :)

chainik_svp
9th March 2015, 22:28
Can someone from you guys please have a look at ffdshow?

and you DO understand that we can wait for it forever? :)

ultim
9th March 2015, 22:31
One "patch" was pretty simple. I have a very dumb way to debug something inside AVS and/or plugins - by placing fprintf.
It's not dumb. A perfectly valid and commonly used method. I use it too, in addition to the CRT debug heap that let's me catch even the smallest leaks that are not visible in the task manager, as well as determine their location.



Again: vfb's are NOT shared between video frames.

So your main point about

doesn't seems to be correct.
Or I'm still missing something :)
Yep, you are. Have a look at VideoFrame::Subframe or ScriptEnv::Subframe.

chainik_svp
9th March 2015, 22:36
... and regardless of whether VFBs shared or not, they still have to be unconditionally deleted in ~ScriptEnvironment()

ultim
9th March 2015, 22:44
... and regardless of whether VFBs shared or not, they still have to be unconditionally deleted in ~ScriptEnvironment()
They are unconditionally deleted, as soon as the last videoframe pointing to them gets deleted. If I didn't have this single condition, the destructor would crash or cause memory corruption due to double-freeing the same memory area when the vfb is referenced multiple times.

chainik_svp
9th March 2015, 22:44
Have a look at VideoFrame::Subframe or ScriptEnv::Subframe.

Good point.

Can you point where exactly in that simplest "BilinearResize" script that SubFrame feature is used? :)
I see now that deleting VFB from VideoFrame will break "sub-frames", BUT was I actually using them?


They are unconditionally deleted

And we're back again.
They are NOT.

ultim
9th March 2015, 22:51
Can you point where exactly in that simplest "BilinearResize" script that SubFrame feature is used? :)
But that destructor has to work for all filters! Not just for BilinearResize that happens to not use subframes.



They are unconditionally deleted
And we're back again.
They are NOT.
Please read my previous post to the end. If I deleted vfbs unconditionally, that would crash (or worse) for filters that use subframes. Again, this cleanup has to work for all filters. Not just for filters that You happen to use.

chainik_svp
9th March 2015, 23:00
In the simple script that using only internal "BilinearResize" filter I'm definitely NOT using "SubFrame" function. Right?
So there should be no frames created through VideoFrame::Subframe().
And still VideoFrame objects are not cleared because of refcount != 0.

I have no idea, may be it's (SubFrame) is called somewhere internally o_O

ultim
9th March 2015, 23:04
In the simple script that using only internal "BilinearResize" filter I'm definitely NOT using "SubFrame" function. Right?
So there should be no frames created through VideoFrame::Subframe().
And still VideoFrame objects are not cleared because of refcount != 0.
Exactly. And this most likely means the host application didn't release the filter chain before destroying the ScriptEnv. Which is why I would like someone to check on ffdshow.
Edit: The reason I find this the most likely reason instead of for example a reference-counting bug in avs+, is because this only happens with a specific version of ffdshow. With any other application, no matter if 32- or 64-bits, this leak could not be observed.

chainik_svp
9th March 2015, 23:20
I've got your point in the end :D

It's not very hard to test ffdshow with Avisynth (2.5.8) x64, right? It should give the very same behavior.

And again, we can wait forever for someone to look into ffdshow code.
As I'm the only one who needs it here, I'll do it... :(

chainik_svp
9th March 2015, 23:58
I can't find any WIN64 specific code in ffdshow.


struct Tinput : Tavisynth_c {
...
IScriptEnvironment* env;
PClip* clip;
...
~Tinput() {
if (clip) {
delete clip;
}
if (env) {
delete env;
}
}
};


But I'm scared of:

struct Tavisynth_c : public Tdll, w/o destructor at all
...
struct Tinput : Tavisynth_c
...
~Tinput()

I'm done for today...

innocenat
10th March 2015, 02:44
Just a quick chime in: ffdshow use Avisynth C interface, with Avisynth API version 2 (according to tryout-trunk). The IScriptEnvironment and PClip are just facade with same interface as the Avs C++ interface, but internally call Avs C interface.

EDIT: There is one mismatch between C interface and C++ interface, mainly in VideoFrame and AVS_VideoFrame structure. It is long vs int problem, though it would only matter if ffdshow is compiled with LP64 data model (not commonly used on windows, but widely on *nix)

jpsdr
10th March 2015, 10:04
EDIT: Notes on using the correct avisynth header. Avs+'s header is compatible with all previously compiled x64 plugins, even those not compiled for Avs+. So using Avs+'s header makes sure you use the correct one as it is also the latest. The very recent Avisynth 2.6 RC1 introduced modifications to the x64 interface which is NOT compatible to any x64 plugin from before, so until the situation is cleared up, I strongly advice you not to use the Avisynth 2.6 header in 64-bit mode, as it will break any and all 64-bit plugins.

I didn't take a look at this new interface, but according your saying, it seems that they finaly want to do what they should have done since the begining, and what was done since the begining in VirtualDub : size_t for pointer, and ptrdiff_t for memory offset. But with all the x64 pluggin allready done, this may be a little to late...

Edit : I took a look... It's not even made properly (at least, from my point of view). Some pitch became size_t, when the right choice would be ptrdiff_t, alowing this way positive and negative offset.

ultim
10th March 2015, 21:40
Edit : I took a look... It's not even made properly (at least, from my point of view). Some pitch became size_t, when the right choice would be ptrdiff_t, alowing this way positive and negative offset.

That'd be still fine in this case. In Avisynth buffer offsets shouldn't be negative anyway, so here a size_t actually fits better than a ptrdiff_t, because it mirrors the developer's intentions more closely. What bothers me is that they did this for... what reason exactly? This change in the interface has no present or future benefit for Avisynth, yet it breaks all existing 64-bit plugins.

Stereodude
10th March 2015, 22:01
This change in the interface has no present or future benefit for Avisynth, yet it breaks all existing 64-bit plugins.
Maybe that was the reason. :scared:

Wilbert
11th March 2015, 19:36
Yes sure that was the reason. If it isn't done correct in the past, that's shouldn't be a reason to do that too in the future. I understand it is very inconvienient for the users of existing 64-plugins and i guess for Avisynth+ users too, and apologies for that, but it shouldn't be too much hassle to recompile the important 64-bit plugins. Or do i miss something and is it a lot of work?

LoRd_MuldeR
11th March 2015, 20:16
Yes sure that was the reason. If it isn't done correct in the past, that's shouldn't be a reason to do that too in the future. I understand it is very inconvienient for the users of existing 64-plugins and i guess for Avisynth+ users too, and apologies for that, but it shouldn't be too much hassle to recompile the important 64-bit plugins. Or do i miss something and is it a lot of work?

Is there any mechanism that prevents the "old"-style x64 plug-in's from loading with the "new"-style x64 Avisynth, or will they simply cause undefined behavior (crash)?

ultim
11th March 2015, 20:18
I'd agree if these changes were any more correct. But you weren't storing pointers in smaller-size integers or doing stupid stuff like that previously, you were just merely limiting the size of an image plane to 2 gigabytes. Since a frame size that large is not in any way realistic, please elaborate how the previous types were more wrong than the new interface. Your reasoning cannot be "because these are pointer offsets", because with that puristical and theoretical argument, the choice of a size_t is equally wrong, as it should be ptrdiff_t then. Fortunately, both size_t and int work perfectly without disadvantages in any real use case. The only practical difference is breaking old plugins or not.

qyot27
11th March 2015, 20:47
What would be necessary for (as mentioned in the RC1 thread concerning what VapourSynth does) storing planes in separate pointers, or for >8bit processing? Or both of those together. Because it sounded like it could be needed by the case of using separate pointers per-plane, and if that's a feature that is planned for 2.6 or some future version, that would be a rationale even without high bit depth support.

I'm mostly just curious about what those things would actually need. libavformat handles the frame size calculation issue by casting to int64_t when reading in the width and height, as you can see here (http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavformat/avisynth.c#l453). If the problem shows up around 9k x 9k @ 8bit, then >8bit would spark it at resolutions that are within cases we might very well see in the near future (like 8K UHD). If it's the same for plugins, anyway (or not a libavformat-specific thing); libavformat is simply taking input from the AviSynth library, not from the plugins.

EDIT: Not that I've tried doing the math to figure out what the maximum allowable frame sizes in a 2GB plane case is. I'm mostly just thinking out loud.

ultim
11th March 2015, 21:04
Storing planes in separate pointers like VS is purely a design decision, and has zero effect on the supported feature set. At most it allows some negligible performance optimizations. The most important thing that Avisynth would need to support more features is to be able to store additional data members in Clip and VideoFrame classes. In a clean solution, that would also be a breaking change to plugins. But even this is solvable without breaking plugins, using hacks in the code and additional complexity, but definitely possible. For supporting >8bit, not even that is necessary, the main thing inhibiting higher bitdepths is upgrading all the plugins and internal functions to work with >8bits: a crazy amount of coding necessary, lot of time, and relatively few people capable at all.

As for handling UHD: a full 9k x 9k frame, even if you take something very odd, like 16bits, no subsampling, RGB interleaved, with alpha transparency (this is about as large as you can get), still only consumes about 618 Mbytes of memory. So even for something crazy like this, the old datatypes were more than enough. So you cannot justify breaking the interface by that.

ultim
11th March 2015, 21:22
Is there any mechanism that prevents the "old"-style x64 plug-in's from loading with the "new"-style x64 Avisynth, or will they simply cause undefined behavior (crash)?

Undefined behavior.

TheFluff
11th March 2015, 22:58
I think you are a bit overly attached to an ABI from like 2002. Especially since almost nobody actually uses 64-bit Avisynth (there was a poll about this a year back or so, IIRC basically nobody claimed to be using 64-bit Avisynth). I was about to say this is a golden opportunity to finally man up and fix that hilariously retarded plugin interface, but then I realized this is Avisynth we're talking about and obviously everything needs to work just like in the 90's or people will hurf a durf.

ultim
11th March 2015, 23:41
I think you are a bit overly attached to an ABI from like 2002. Especially since almost nobody actually uses 64-bit Avisynth (there was a poll about this a year back or so, IIRC basically nobody claimed to be using 64-bit Avisynth). I was about to say this is a golden opportunity to finally man up and fix that hilariously retarded plugin interface, but then I realized this is Avisynth we're talking about and obviously everything needs to work just like in the 90's or people will hurf a durf.

Yes, if you are going to break the interface anyway, just man up as you say and do it correctly, and correct all the other mistakes too. Oh wait, you cannot, because then for those other changes you'd have to break to 32-bit interface too, and that interface /is/ used by a lot of people.

You make it sound like I just want to stay by the old interface no matter what. Wrong! I am not against this change because it touches some old stuff. I am against it because it doesn't bring any kind of benefit, but causes problems. If there is a good reason, like correcting design mistakes, modernizing it, adding new features, or anything along these lines, I'd just go with it. But this change was none of them, yet makes all plugins from the past 6+ years unusable.

Avisynth+ will break the interface in the future, moreoever, it will do it drastically. It is already being planned. But, very importantly, it will do it only once, for real benefits and progress, and will do it in a sustainable way such that breaking modification won't be necessary again after that. And I am waiting for it eagerly, and I won't shed a single tear for the old interface. But this needs preparation, both on Avisynth's core's side as well on the plugins' side.

Make it personal if you really want to. But in the end, every real programmer should see this is not about "manning up", or throwing false accusations around that I just love stuff from the 90's. It is about careful preparation, waiting out until stuff is ready, then doing the change responsibly in the end.

Stereodude
12th March 2015, 00:08
Especially since almost nobody actually uses 64-bit Avisynth (there was a poll about this a year back or so, IIRC basically nobody claimed to be using 64-bit Avisynth).
I use it extensively along with MP_Pipeline for mixing 32-bit and 64-bit. Even if all the scripting is really in 32-bit at the very least its very handy to feed x264 64-bit without having to pipe it.

jpsdr
12th March 2015, 09:28
Especially since almost nobody actually uses 64-bit Avisynth
ME !!! ME !!! ME !!!
I am, i am, i am !!!
;)

And i love stuff from 90's, even 80's, it was my youth.:p

kaefert
12th March 2015, 11:25
I also use 64bit, since with avisynth 32bit my scripts simply won't work at all. I'm using avisynth as a non-linear video editor therefore my scripts have A LOT of input streams which simply bursts the memory limitations of 32bit.

ultim
12th March 2015, 13:26
So you are writing your own AviSynth plugin (cool!), and obviously one of the first things you have to do in your code is to include the AviSynth header. But which one? With all the different header variants lying around it is easy to get lost if you haven't been following AviSynth's development for a long time. Should you copy the header from another plugin? Should you copy it from the AviSynth64 project to be 64-bits compatible? Should you take the 2.5 header as it is the latest release that is officially stable? Do you need SEt's AviSynth-MT header if you want multithreading compatibility? Do you need seperate headers for 32- and 64-bits like most plugins ship it? Should you just take the latest header from the AviSynth 2.6 project? And what about AviSynth+'s header?

Fortunately, no matter how you answer the above questions, there is one (and just one) solution that is easy to implement and fits all needs: Use AviSynth+'s header. And if you'd like to know why, read on.

So let's tackle the above questions.

Should you copy the header from another plugin?
No. Most plugins are older then AviSynth project releases, and so they ship with outdated (and sometimes buggy) headers. Also, some plugins have both separate 32- and 64-bit sources, so you still wouldn't know which one to take. And if you are really unlucky, you might stumble on a plugin that was written for AviSynth 2.5, and using that header would be the worst of all your header-related options.

Should you take the 2.5 header as it is the latest release that is officially stable?
No. 2.5 is no more. Most plugins that have originally been written for 2.5 have been already recompiled for 2.6. Don't try to be smart and support both versions, because they are not compatible. 2.6 has been around for many years now, and the existing plugin ecosystem builds exstensively around this version. Technically speaking, it is stable. Nobody uses 2.5 any more.

Should you copy it from the AviSynth64 project to be 64-bits compatible?
No. While AviSynth64's header will work perfectly if you want your plugin to *only* run in 64-bit mode, that is most likely not the case. That project isn't maintained any more, and thanks to that the 32-bit part is out of date.

Do you need seperate headers for 32- and 64-bits like most plugins ship it?
No. You will see plugins around that have both avisynth.h and avisynth64.h. Same for many applications hosting avisynth.dll. This is because the original AviSynth project never supported 64-bit processing (not even today), so these other projects took the 32-bit header from the latest AviSynth version that was available when they were created, and they took the 64-bit header from the AviSynth64 project. This resulted in an ecosystem where the 64-bit versions didn't see any improvements over the years. On the upside, avisynth64.h stayed stable. On the downside, the 32-bit and 64-bit headers started drifting apart. Nevertheless, a merge of the avisynth.h and avisynth64.h headers is easily possible, which is exactly what AviSynth+ has done. There is no need for two separate headers, it only results in additional code, complexity, and maintenance burden.

Do you need AviSynth-MT's header if you want multithreading compatibility?
No. While properly supporting multithreaded versions does require special coding considerations from plugin writers (see this other article (http://forum.doom9.org/showthread.php?p=1649886#post1649886)), none of those considerations affect the choice of header. There is no API or ABI difference between multi-threaded and single-threaded AviSynth versions. You can perfectly support MT-capable AviSynth versions even if using the header from an AviSynth variant that has no MT-support.

Should you just take the latest header from the AviSynth 2.6 project?
No. This project (sometimes people refer to it as the "original" or "official" AviSynth, though somewhat incorrect (http://forum.doom9.org/showthread.php?p=1693944#post1693944)) always has the latest version, but it will do you no good if you want to support 64-bit processing. You cannot compile your plugin using its header in 64-bit mode, which is why people started using avisynth64.h in the first place. Even if it decided to support 64-bit in the future, it wouldn't be compatible to the existing (and pretty large) 64-bit ecosystem anymore, throwing away all the 64-bit plugin and application development that has been done in the past 6 years or so. And as already said, using two separate headers is completely unnecessary and only leads to additional complications down the road.

What about AviSynth+'s header?
The headers of AviSynth+ (https://github.com/AviSynth/AviSynthPlus/tree/MT/avs_core/include) are up to date in every aspect and provide the greatest possible compatibility. By using AviSynth+'s headers, applications and plugins can cleanly compile and run in 32-bits and 64-bits. It is 100% compatible to the latest 32-bit development on the old AviSynth 2.6 project, while supporting all 64-bit binaries. And of course, you can use it regardless if you support multithreading or not. Furthermore and importantly, it is fully compatible to installations of the AviSynth 2.6, AviSynth-MT, AviSynth64, and of course the AviSynth+ projects, so your plugin/application will be able to run on any user's machine.

chainik_svp
12th March 2015, 13:46
ultim
Use AviSynth+'s header.

So why it still contains that "normal licence conditions will be reapplied in a future version" thing from AVS 2.6 header? :)

ultim
12th March 2015, 14:09
ultim
Use AviSynth+'s header.

So why it still contains that "normal licence conditions will be reapplied in a future version" thing from AVS 2.6 header? :)

The 2.6 header is originally written by Ianb, and even though we have made a derivative work of it, we cannot legally relicense the header without his explicit permission. LGPL-like condiitons (even if technically not LGPL) will be restored when 2.6 exits the RC stage, or when Avisynth+ creates a 100% new header, whichever comes first.

chainik_svp
12th March 2015, 14:19
So actually there's still a room for good old 2.5 headers...

// Avisynth v2.6. Copyright 2006 Klaus Post.
// Avisynth v2.6. Copyright 2009 Ian Brabham.
What will come first - GRRM will finish "Song of ice and fire" or Avisynth 2.6 will exit RC stage?

Reel.Deel
12th March 2015, 14:38
Especially since almost nobody actually uses 64-bit Avisynth (there was a poll about this a year back or so, IIRC basically nobody claimed to be using 64-bit Avisynth).

Maybe because that thread (http://forum.doom9.org/showthread.php?t=168478) was created before AviSynth+ came into fruition. Also 64-bit avs was not even an option. I'm sure the number of users has grown since AviSynth+.

ultim
12th March 2015, 14:39
So actually there's still a room for good old 2.5 headers...


What will come first - GRRM will finish "Song of ice and fire" or Avisynth 2.6 will exit RC stage?

Of course, this is only a problem if you want to distribute a closed-source application or filter. Closed source binaries must use a header from before Aug 14, 2009.

ultim
12th March 2015, 15:05
Maybe because that thread (http://forum.doom9.org/showthread.php?t=168478) was created before AviSynth+ came into fruition. Also 64-bit avs was not even an option. I'm sure the number of users has grown since AviSynth+.

Yeah, it's kind of hard to vote for something if it isn't even an option in the poll. LOL

martin53
12th March 2015, 19:21
Oh my gosh, I bet it has to do something with AviSynth's StringDump. This is only a hunch though. Is it reproducible on classic Avisynth, even if only sporadically?

I instrumented the script to report the processing of most lines via DbgView, see embedded code. This script ran several dozen times with 2.6 MT without fail in patched AvsPmod. After I lost patience today and installed Avisynth+ r1576, AvsPmod crashed in several runs and paused (maybe better term than freeze here) in all other runs, between line 124 and 125. Try {RT_Version()} catch (msg) {assert(false,"This script requires the RT_Stats plugin.")}
Try {GEval("")} catch (msg) {assert(false,"This script requires the GScript plugin.")}
global ofs=0

#============================================================================
Filename=RT_FSelSaveAs(title="Save Filter list",dir="",filt="Text files|*.txt",fn="_All+Functions_.txt",debug=true)
Assert(FileName.IsString(), "Please provide a file name to save the filter list")

#============================================================================
RT_WriteFile(Filename, VersionString(), Append=false) Try {assert(false)} catch(err) {Line(err,0)}
WriteInternalFunctionsSyntax(RT_InternalFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntaxBackward(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntax(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntaxBackward(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntax(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntaxBackward(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntax(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
WritePluginFunctionsSyntaxBackward(RT_PluginFunctions(), Filename) Try {assert(false)} catch(err) {Line(err,0)}
BlankClip().subtitle("Function info is complete.",align=5)

#============================================================================
function WriteInternalFunctionsSyntax(string fu_list, string Filename) {
Try {assert(false)} catch(err) {Line(err,0)}
GScript("""
done="" Try {assert(false)} catch(err) {Line(err,23)}
while(fu_list != "") {
i = FindStr(fu_list+" ", " ") Try {assert(false)} catch(err) {Line(err,23)}
fu_name = LeftStr(fu_list, i-1) Try {assert(false)} catch(err) {Line(err,23)}
fu_list = MidStr(fu_list, i+1) Try {assert(false)} catch(err) {Line(err,23)}
params = RT_PluginParam(fu_name) Try {assert(false)} catch(err) {Line(err,23)}
if (FindStr(done, fu_name+params)==0) {
done = done + " "+fu_name+params Try {assert(false)} catch(err) {Line(err,23)}
RT_WriteFile(Filename, "internal %s ( %s ) -> %s", fu_name, params, GetReturnType(fu_name, params), Append=true)
Try {assert(false)} catch(err) {Line(err,23)}
}
}
""")
}
#============================================================================
function WritePluginFunctionsSyntax(string fu_list, string Filename) {
Try {assert(false)} catch(err) {Line(err,0)}
GScript("""
done="" Try {assert(false)} catch(err) {Line(err,41)}
while(fu_list != "") {
i = FindStr(fu_list+" ", " ") Try {assert(false)} catch(err) {Line(err,41)}
fu_name = LeftStr(fu_list, i-1) Try {assert(false)} catch(err) {Line(err,41)}
fu_list = MidStr(fu_list, i+1) Try {assert(false)} catch(err) {Line(err,41)}
i = FindStr(fu_name, "_") Try {assert(false)} catch(err) {Line(err,41)}
if (i>0) {
params = RT_PluginParam(fu_name) Try {assert(false)} catch(err) {Line(err,41)}
if (FindStr(fu_list, "_"+fu_name)==0 && FindStr(done, "_"+fu_name+params)==0) {
done = done + " _"+fu_name+params Try {assert(false)} catch(err) {Line(err,41)}
RT_WriteFile(Filename, "plugin %s ( %s ) -> %s", fu_name, params, GetReturnType(fu_name, params), Append=true)
Try {assert(false)} catch(err) {Line(err,41)}
}
}
}
""")
}
#============================================================================
function WritePluginFunctionsSyntaxBackward(string fu_list, string Filename) {
Try {assert(false)} catch(err) {Line(err,0)}
GScript("""
done="" Try {assert(false)} catch(err) {Line(err,62)}
fu_list = RevStr(fu_list) Try {assert(false)} catch(err) {Line(err,62)}
while(fu_list != "") {
i = FindStr(fu_list+" ", " ") Try {assert(false)} catch(err) {Line(err,62)}
fu_name = RevStr(LeftStr(fu_list, i-1)) Try {assert(false)} catch(err) {Line(err,62)}
fu_list = MidStr(fu_list, i+1) Try {assert(false)} catch(err) {Line(err,62)}
i = FindStr(fu_name, "_") Try {assert(false)} catch(err) {Line(err,62)}
if (i>0) {
params = RT_PluginParam(fu_name) Try {assert(false)} catch(err) {Line(err,62)}
if (FindStr(fu_list, "_"+fu_name)==0 && FindStr(done, "_"+fu_name+params)==0) {
done = done + " _"+fu_name+params Try {assert(false)} catch(err) {Line(err,62)}
RT_WriteFile(Filename, "plugin %s ( %s ) -> %s", fu_name, params, GetReturnType(fu_name, params), Append=true)
Try {assert(false)} catch(err) {Line(err,62)}
}
}
}
""")
}
#============================================================================
#function GetReturnType(string fu, string params) { r = "?" }
#============================================================================
function GetReturnType(string fu, string params) {
Try {assert(false)} catch(err) {Line(err,0)}
GScript("""
RT_DebugF("Fu=%s %s", fu, params, name="GetReturnType") Try {assert(false)} catch(err) {Line(err,86)}
if (MidStr(fu,3,1)=="+") {fu = LeftStr(fu,2)+MidStr(fu,2) Try {assert(false)} catch(err) {Line(err,86)}}
if (MidStr(fu,2,1)=="+") {fu = LeftStr(fu,1)+fu Try {assert(false)} catch(err) {Line(err,86)}}
else if (fu=="Assert") {r = "conditional halt" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "avss_26_DSS2")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "ImageSeq_")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "LoadCPlugin")>0) {r = "void" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "LoadVirtualdubPlugin")>0) {r = "void" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "MDepan")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "MSCDetection")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "mvtools2_")>0) {r = "clip?" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "ResampleAudio")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "Resize")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "RT_Debug")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "RT_FSel")>0) {r = "." Try {assert(false)} catch(err) {Line(err,86)}}
else if (FindStr(fu, "Source")>0) {r = "clip" Try {assert(false)} catch(err) {Line(err,86)}}
else {
bc = BlankClip(width=8,height=8,length=1,pixel_type="YV12")
Try {assert(false)} catch(err) {Line(err,86)}
fp = LeftStr(params,2)=="cc" ? "(bc,bc)"
\ : LeftStr(params,2)=="cf" ? "(bc,0.1)"
\ : LeftStr(params,3)=="cci" ? "(bc,bc,0)"
\ : LeftStr(params,5)=="ciiii" ? "(bc,0,0,0,0)"
\ : LeftStr(params,4)=="ciii" ? "(bc,0,0,0)"
\ : LeftStr(params,3)=="cii" ? "(bc,0,0)"
\ : LeftStr(params,2)=="ci" ? "(bc,0)"
\ : LeftStr(params,1)=="c" ? "(bc)"
\ : LeftStr(params,2)=="ff" ? "(0.1,0.1)"
\ : LeftStr(params,1)=="f" ? "(0.1)"
\ : LeftStr(params,2)=="ii" ? "(0,0)"
\ : LeftStr(params,1)=="i" ? "(0)"
\ : LeftStr(params,2)=="ss" ? "("+chr(34)+"1"+chr(34)+","+chr(34)+"1"+chr(34)+")"
\ : LeftStr(params,2)=="si" ? "("+chr(34)+"1"+chr(34)+",1)"
\ : LeftStr(params,1)=="s" ? "("+chr(34)+"1"+chr(34)+")"
\ : "()" Try {assert(false)} catch(err) {Line(err,86)}
Try {
Try {assert(false)} catch(err) {Line(err,86)}
r = Eval("current_frame=0 "+fu+fp) Try {assert(false)} catch(err) {Line(err,86)}
r = r.IsBool ? "bool" : r.IsClip ? "clip" : r.IsInt ? "int" : r.IsFloat ? "float" : r.IsString ? "string" : "?"
Try {assert(false)} catch(err) {Line(err,86)}
} catch (msg) {
Try {
r = r.IsBool ? "bool" : r.IsClip ? "clip" : r.IsInt ? "int" : r.IsFloat ? "float" : r.IsString ? "string" : "?"
} catch(msg) {
r = "?" Try {assert(false)} catch(err) {Line(err,86)}
}
}
if (r=="?") {
bc = BlankClip(width=8,height=8,length=1,pixel_type="RGB32")
Try {assert(false)} catch(err) {Line(err,86)}
fp = LeftStr(params,2)=="cc" ? "(bc,bc)"
\ : LeftStr(params,2)=="cf" ? "(bc,0.1)"
\ : LeftStr(params,3)=="cci" ? "(bc,bc,0)"
\ : LeftStr(params,5)=="ciiii" ? "(bc,0,0,-0,-0)"
\ : LeftStr(params,4)=="ciii" ? "(bc,0,0,0)"
\ : LeftStr(params,3)=="cii" ? "(bc,0,0)"
\ : LeftStr(params,2)=="ci" ? "(bc,0)"
\ : "(bc)" Try {assert(false)} catch(err) {Line(err,86)}
Try {
Try {assert(false)} catch(err) {Line(err,86)}
r = Eval("current_frame=0 "+fu+fp) Try {assert(false)} catch(err) {Line(err,86)}
r = r.IsBool ? "bool" : r.IsClip ? "clip" : r.IsInt ? "int " : r.IsFloat ? "float" : r.IsString ? "string" : "?"
Try {assert(false)} catch(err) {Line(err,86)}
} catch (msg) {
r = "?" Try {assert(false)} catch(err) {Line(err,86)}
}
}
if (r=="?" && LeftStr(params,1)=="c") {r="clip?" Try {assert(false)} catch(err) {Line(err,86)}}
}
""")
Try {assert(false)} catch(err) {Line(err,0)}
return r
}
#=====================================================================================================================
function Line(string s, int ofs) {ofs=default(ofs,0) s=RightStr(s,FindStr(RevStr(s)," ")-1) s=LeftStr(s,StrLen(s)-1) l=int(value(s)+ofs) RT_DebugF("%d",l,name="@line ")}
#=====================================================================================================================

Script may look complicated first but is easy to understand I think. Best I can do today is provide this 'tool' to provoke the failure.
I do assume that the behavior is machine-dependent, since FFT plugins make it more prone to fail,
When reproducing, note that line numbers are logged after the command in that line.

qyot27
12th March 2015, 20:34
With the recent changes to how the version information is generated internally, was it intentional that the output of Version() itself doesn't use AVS_FULLVERSION now, but only AVS_PROJECT and AVS_COPYRIGHT?

ultim
12th March 2015, 21:02
With the recent changes to how the version information is generated internally, was it intentional that the output of Version() itself doesn't use AVS_FULLVERSION now, but only AVS_PROJECT and AVS_COPYRIGHT?

Of course not. Fixed :D

jpsdr
13th March 2015, 10:34
@Ultim
I've updated as you adviced my avisynth.h to your's last version.
I've been obliged to make the following changes :
Replace all the

<avs/xxx.h>

with

"./avs/xxx.h"

For a redistribuable header for creating pluggins, i think it would be better to use "" version instead of <>.

My real question indeed, is : When i tried to recompile my filters, i have one which use "CACHE_25_RANGE". I guess remplacement should be "CACHE_GET_RANGE", but i want to be sure. Thanks.

The exact code is :

child->SetCacheHints(CACHE_25_RANGE,3);
.....
v.AsClip()->SetCacheHints(CACHE_25_RANGE,2);

innocenat
13th March 2015, 10:50
I think it was decided (for Avs+), that you should include $AVISYNTH_INSTALL_DIR/include to your project include directory inatead of copy them everywhere.

jpsdr
13th March 2015, 12:14
That's work only if you have avs+ installed, maybe not if you have avs2.6.
Well... it realy doesn't matter, this issue is not a big deal.