View Full Version : Avisynth+
turbojet
30th September 2013, 06:51
All I could find for avsynth is https://github.com/LRN/gst-avsynth which seems abandoned, does ffmpeg have something in the pipe named AVsynth?
I agree avi is still useful but modern lossy encoders have given it a bad name and often seen as a last resort or unsupported.
ultim
30th September 2013, 08:01
... and it's still subject to the huge caveat that C plugins aren't included in the autoloading feature.
Since when? Oh sorry, I've forgot you're not using ultim's build ;)
I wanted to get a release out yesterday in the evening (CET), but I've realized last minute that the new shadow plugin folder feature's API could be improved, so I've delayed. I hope I'll be able to release tonight, but no guarantees, since I'll be getting home later today.
And yes, the above means C plugins are autoloaded with my rewritten plugin management, I worked on that since I was also missing that feature, and find it very useful and even necessary to encourage using it.
Yes, simply linking with "nothrownew.obj" (which ships with VC10) keeps "new" from throwing "bad_alloc".
That works too, but I prefer a standards compliant implementation so I've chosen another way. I went ahead and inspected where "new" is used to find places where we depended upon it returning NULL, and changed those occurrences to the non-throwing (std::nothrow) version. This way we are not only compliant to the c++ standards, but we also don't require to link with special MS-specific object files.
p.s. I still haven't decided on a name so keep 'em coming :)
qyot27
30th September 2013, 09:27
All I could find for avsynth is https://github.com/LRN/gst-avsynth which seems abandoned, does ffmpeg have something in the pipe named AVsynth?
That's not what I was saying. Naming conventions for lots of API and function stuff in the libav* libraries start with AV_ - so steering clear of stuff approaching that would be advisable.
Since when? Oh sorry, I've forgot you're not using ultim's build ;)
I wanted to get a release out yesterday in the evening (CET), but I've realized last minute that the new shadow plugin folder feature's API could be improved, so I've delayed. I hope I'll be able to release tonight, but no guarantees, since I'll be getting home later today.
And yes, the above means C plugins are autoloaded with my rewritten plugin management, I worked on that since I was also missing that feature, and find it very useful and even necessary to encourage using it.
I was hoping as much when plugin management got mentioned before. Huzzah.
I've been refining the build instructions some, now that I've also got the DirectShowSource-related stuff documented step-by-step.
raffriff42
30th September 2013, 13:31
Just brainstorming here...
MediaSynth
Avisinthe
ASST (AviSynthyServerThingy)
AINRA (AINRA Is Not Really Avisynth)
AVI Normal (does this need explaining? Young Frankenstein?)
kypec
30th September 2013, 15:31
ModAviSynth is my proposal which should define this fork as modern and modified project at the same time. Thumbs up, ultim and :thanks: for all your hard work on improving AviSynth.
VapourSynth looks promising but not yet quite there. ;)
ultim
30th September 2013, 18:43
Thank you everybody for the suggestions. Right now I'm leaning towards qyot27's "AviSynth+". I find it good because it expresses exactly what the project is, and what its intention is. It makes it easy to distinguish between the two projects, while it still notes that it is rooted in Avisynth, and has a clear message that it is supposed to be an enhanced version of the original project.
mastrboy
30th September 2013, 19:38
Wouldn't a single "+" make it a little hard to search for? Considering it's interpreted as an operator by most search engines?
qyot27
30th September 2013, 21:00
The + could simply be the stylized name that appears in say, the output of Version(). Having it written out as 'Plus' in other places like the Github repo URL would be fine.
Reel.Deel
1st October 2013, 01:34
+1 for "AviSynth+", I've tried to think of other names but that's a tough one to beat.
raffriff42
1st October 2013, 02:04
Buy the domain name now, or it might get squatted upon. ;)
hanfrunz
1st October 2013, 09:26
What avisynth development really needs is a meeting of some of the core developers in person. I have no idea if this is possible, but an avisynth developer conference/camp would be cool. Maybe you find another conference, where you could meet. For example the 30c3 (https://events.ccc.de/congress/2013/wiki/Main_Page) in Germany this december, etc.
Groucho2004
1st October 2013, 11:26
What avisynth development really needs is a meeting of some of the core developers in person.
As far as I know, IanB is The Last Man Standing from that group.
ultim
1st October 2013, 21:22
Yuhuuuu, new build, and new code on GitHub!
So, what has changed:
- First of all, the crash-on-out-of-memory bug is hopefully fixed. Should be.
- There is a brand new plugin-system in place, and if you work with scripts that use a lot of plugins, you should notice that they load faster.
- You can have multiple plugin directories. Exact semantics in my next post.
- LoadCPlugin (or Load_Stdcall_Plugin) is now a synonym for LoadPlugin. LoadPlugin will load C-plugins and LoadCPlugin will load normal plugins. They are one and the same. No difference.
- Hence, C plugins are also autoloaded.
- LoadVFAPIPlugin() is out of order for now. I'm not planning on removing it, I just need some info how to correct it.
Changes noteworthy for developers:
- Invoke finally stops throwing exceptions as a "normal condition" -> better debuggability
- VFAPI and VirtualDub filter loading are now separated into their own plugins, and are not in core any more.
ultim
1st October 2013, 21:42
Okay, so how do multiple plugin directories interact with plugin autoloading?
As a recap, here is how it used to work in the official Avisynth:
- Look for the string HKEY_CURRENT_USER/Software/Avisynth/PluginDir2_5 in the registry. If it exists, load plugins from the path specified there and stop.
- If the above string didn't exist, look in HKEY_LOCAL_MACHINE/Software/Avisynth/PluginDir2_5. Try to load plugins from the path specified there.
- Done.
First thing to note, is that classic Avisynth only ever searches for plugins in one single directory. It only knows two directories (both specified in the registry), and it only tries the second path if there is no entry for the first one.
Avisynth+'s autoloader has a list of autoload directories. It iterates over all those directories and tries to load all plugins from each. But (and a big but!) it will not load a plugin from a directory if another plugin with the same basename is already loaded. The basename of a plugin is simply its file name without the extension.
The expected use case is that you can now overlay a new plugin directory on top of another one. Avisynth+ then would load all plugins from the first folder, then load only those plugins from the second that weren't loaded from the first, then those from the third that weren't loaded from the first or second and so on. For example, let's say your usual plugin folder has a lot of plugins you normally use. But at one time you have a small number of updated plugins that you only want to use from a few scripts, but you do not yet want to replace your existing plugins globally. Then you'd just add a new plugin overlay folder, with only the new plugins in it, and that's it. All scripts that specify the new folder will autoload all plugins from your usual one, except for the new plugins, which would get loaded from the new folder. All your other scripts will still use your old plugins.
My next post will tell you how to add and remove autoload folders.
Groucho2004
1st October 2013, 21:51
Avisynth+'s autoloader has a list of autoload directories. It iterates over all those directories and tries to load all plugins from each. But (and a big but!) it will not load a plugin from a directory if another plugin with the same basename is already loaded. The basename of a plugin is simply its file name without the extension.
Might be a bad idea. Take for example the RemoveGrain package. It has several DLLs, each built with different optimizations (SSE, SSE2, etc.). They are named "RemoveGrainSSE.dll", "RemoveGrainSSE2.dll", you get the idea. Yet, they all have the same name in AvisynthPluginInit. I bet that 3 out of 4 users dump the lot in their autoload directory.
Groucho2004
1st October 2013, 21:52
First of all, the crash-on-out-of-memory bug is hopefully fixed. Should be.
Yes, it is. :)
ultim
1st October 2013, 22:09
By default, Avisynth+'s autoload folder list has four paths in it, in this order:
- PluginDir+ in Software/Avisynth in HKEY_CURRENT_USER
- PluginDir+ in Software/Avisynth in HKEY_LOCAL_MACHINE
- PluginDir2_5 in Software/Avisynth in HKEY_CURRENT_USER
- PluginDir2_5 in Software/Avisynth in HKEY_LOCAL_MACHINE
This means, if there are ever plugins which will only work with Avs+ but not with classic Avs, you can put them into one of the "PluginDir+" folders. Avisynth+ will then use the classic plugins from the normal Avisynth, but if there are versions of some plugins written for Avisynth+, it will use them instead, and the classic avisynth.dll will still not be bothered with them. This is all without you having to lift a finger (except for adding the "PluginDir+" values to the registry once, until we have an installer). So to summarize all this, you have the ability to define a plugin autoload folder in the registry which will only be used by Avs+, but not by Avs, in addition to your classic plugins.
However, another new functionality offered by Avisynth+, is that now you can also specify autoload paths in the scripts. There are two functions for this:
- AddAutoloadDir(string path, bool toFront): this will add a new autoload folder. The string parameter is obligatory, it is the folder path where to load from. The second boolean parameter is optional, and if true (default), it will add the path to the front/beginning of the autoloader's list, which means it will be searched earlier than the rest. If it is false, the path will get added to the end of the list, so it will get searched last (unless you again add another one to the end).
- ClearAutoloadDirs(): This will clear all the paths from the autoloader's list. Note that it is NOT a reset to the default state. ClearAutoloadDirs() will clear all folders, so if you don't add new ones after that, you have disabled the autoload functionality. This is, BTW, also a way to disable autoloading for a particular script in Avisynth+.
Here's an important note: You can only call these functions if no plugin has been autoloaded yet. Autoloading happens if the first unknown function is looked up. This means you can only call AddAutoloadDir or ClearAutoloadDirs if you have only made calls to built-in functions up to that point in the script. I suggest you start your scripts with these calls to avoid any problems.
There is only one thing left to discuss: Are there any special directories you can reference from your script? You bet there are :)
- SCRIPTDIR is the folder of the most current script. It is the path of the imported script if your script calls import()
- MAINSCRIPTDIR is the folder of your main script, the one where execution started
- PROGRAMDIR is the folder of the executable running the current script
- USER_PLUS_PLUGINS is the string stored in PluginDir+ in Software/Avisynth in HKEY_CURRENT_USER
- MACHINE_PLUS_PLUGINS is the string stored in PluginDir+ in Software/Avisynth in HKEY_LOCAL_MACHINE
- USER_CLASSIC_PLUGINS is the string stored in PluginDir2_5 in Software/Avisynth in HKEY_CURRENT_USER
- MACHINE_CLASSIC_PLUGINS is the string stored in PluginDir2_5 in Software/Avisynth in HKEY_LOCAL_MACHINE
... all these special constants are case-sensitive for now.
Examples
- If you want plugins to be autoloaded from the script's "autoload" directory too, you'd write:
AddAutoloadDir("MAINSCRIPTDIR/autoload")
- If you want plugins to be autoloaded from the script's "autoload" directory, only from there and nowhere else, you'd write:
ClearAutoloadDirs()
AddAutoloadDir("MAINSCRIPTDIR/autoload")
- If you wanted to manually recreate the default state of the autoloading folder list, you'd write:
ClearAutoloadDirs()
AddAutoloadDir("USER_PLUS_PLUGINS", false)
AddAutoloadDir("MACHINE_PLUS_PLUGINS", false)
AddAutoloadDir("USER_CLASSIC_PLUGINS", false)
AddAutoloadDir("MACHINE_CLASSIC_PLUGINS", false)
ultim
1st October 2013, 22:30
Might be a bad idea. Take for example the RemoveGrain package. It has several DLLs, each built with different optimizations (SSE, SSE2, etc.). They are named "RemoveGrainSSE.dll", "RemoveGrainSSE2.dll", you get the idea. Yet, they all have the same name in AvisynthPluginInit. I bet that 3 out of 4 users dump the lot in their autoload directory.
Yes, in this case they'd be "recognized" as separate plugins. But even if Avs+ could tell that they are different versions of the same plugin, it still wouldn't be able to decide which one to load (for that it'd neeed some mechanism to determine the used optimizations in a binary, which is not really feasable). So the choice of a different basename wouldn't really help here anyway, AFAICT. The problem is really that RemoveGrain doesn't use dynamic dispatching of routines based on the current machine's instruction set.
Groucho2004
1st October 2013, 22:52
The problem is really that RemoveGrain doesn't use dynamic dispatching of routines based on the current machine's instruction set.
Removegrain was just an example and yes, the missing CPU dispatcher is the problem.
Another thing is to improve somehow the detection of garbage in the autoload directories (i.e. old plugins which are incompatible with 2.6). However, querying the interface version for each plugin every time would probably be too time consuming.
qyot27
2nd October 2013, 00:07
What about an index that caches the necessary functions out of the plugins (maybe something like what fontconfig does, where the cache is only regenerated when it detects a change in the directory contents)? Would that allow more flexibility to determine which version of a plugin should be used or which plugins actually get autoloaded? Checking a cache file would probably be a lot faster than checking the plugins themselves, right?
Gavino
2nd October 2013, 00:37
- If you want plugins to be autoloaded from the script's "autoload" directory too, you'd write:
AddAutoloadDir("MAINSCRIPTDIR/autoload")
In what contexts do MAINSCRIPTDIR and the other 'special' names get replaced with the corresponding folders?
In all strings, or only when used in the argument to AddAutoloadDir?
qyot27
2nd October 2013, 02:00
On the C-plugin autoloading front, I can verify that AssRender now autoloads, but FFMS2's C-plugin (github.com/FFMS/ffms2/commits/c_plugin) does not, even when I try to load it with LoadPlugin.
On a guess, I think it *might* have to do with FFMS2 using the same modified-for-2.6-colorspaces version of avisynth_c.h that x264 and FFmpeg do. So a feature request would be to merge in those changes and finally bring avisynth_c.h up to speed.
qyot27
2nd October 2013, 06:46
The build instructions I posted earlier have been revamped and fleshed out. It now includes DirectShowSource setup.
ultim
2nd October 2013, 08:27
Another thing is to improve somehow the detection of garbage in the autoload directories (i.e. old plugins which are incompatible with 2.6). However, querying the interface version for each plugin every time would probably be too time consuming.
I'm not sure if that is what you mean, but both Avs and Avs+ already query interface versions. They try to load the 2.6 interface from a plugin first, and if that is not supported, they try to load the 2.5 interface. Avs+ also tries to load the C interface if both of the previous ones fail. In the future, the C interface should probably be prioritized over 2.5.
What about an index that caches the necessary functions out of the plugins (maybe something like what fontconfig does, where the cache is only regenerated when it detects a change in the directory contents)? Would that allow more flexibility to determine which version of a plugin should be used or which plugins actually get autoloaded? Checking a cache file would probably be a lot faster than checking the plugins themselves, right?
I'm not sure how that would help. Even if it detected a plugin was changed/added/removed, that still doesn't tell us much about whether it is the "correct" version. Can you elaborate on your idea further?
As a side note, because Avs(+) doesn't have a continuously running process in the background, plugin change detection cannot be implemented efficiently. Even fontconfig has to be notified from an external application if the font folder changes. And purely for performance, implementing a plugin cache isn't needed for Avisynth. As a comparison, there are much fewer plugins than fonts, and the plugins are also much smaller.
In what contexts do MAINSCRIPTDIR and the other 'special' names get replaced with the corresponding folders?
In all strings, or only when used in the argument to AddAutoloadDir?
Only in AddAutoloadDir(), and even there, only if they are at the very beginning of the string. These get replaced to absolute folder paths, so if they are not at the beginning of the string, replacing them would only result in an invalid path (e.g. you'd end up with "c:" in the middle of your path).
On the C-plugin autoloading front, I can verify that AssRender now autoloads, but FFMS2's C-plugin (github.com/FFMS/ffms2/commits/c_plugin) does not, even when I try to load it with LoadPlugin.
On a guess, I think it *might* have to do with FFMS2 using the same modified-for-2.6-colorspaces version of avisynth_c.h that x264 and FFmpeg do. So a feature request would be to merge in those changes and finally bring avisynth_c.h up to speed.
Nice spotting. I'll have a look at it when I get home.
The build instructions I posted earlier have been revamped and fleshed out. It now includes DirectShowSource setup.
Thx.
qyot27
2nd October 2013, 21:40
I'm not sure how that would help. Even if it detected a plugin was changed/added/removed, that still doesn't tell us much about whether it is the "correct" version. Can you elaborate on your idea further?
As a side note, because Avs(+) doesn't have a continuously running process in the background, plugin change detection cannot be implemented efficiently. Even fontconfig has to be notified from an external application if the font folder changes. And purely for performance, implementing a plugin cache isn't needed for Avisynth. As a comparison, there are much fewer plugins than fonts, and the plugins are also much smaller.
The original idea actually was rooted in how I understood the original AviSynth's plugin autoloading to work, where all plugins in the autoload folder were loaded so it could identify where functions were, then everything was unloaded, and finally the necessary ones were loaded again. That initial step could cause issues if a plugin was prone to crashing, even if said plugin wasn't even used in the script (one of the variants of WarpSharp was known to cause issues like this).
The cache idea was mostly thought up to avoid that scenario, since it would store the names and plugin locations of the functions and avoid having to perform those first two steps and any instability that could cause - instead, it'd read the cache, compare it to the script, and then load only the plugins used in the script.
But if there's an issue with plugin name collisions, a cache might allow for user overrides on a plugin-specific level while still keeping the new directory priorities the same (in the original project, I'm pretty sure this is why the ability to prefix the function with the name of the dll was added: dgdecode_MPEG2Source vs. mpeg2dec3_MPEG2Source, even though that's the case of the same function, but different .dll names - having it user-customizable would remove the need for special prefixing since the user could set whichever plugin they want as the default, and it would cover cases if the plugin and function names were the same, since the user could have the ability to set an alias of their own in the cache). Or in the RemoveGrain example, it could use a separate CPU dispatching plugin or function and the cache could be used to prioritize which version would take priority on the host CPU.
Regarding FFMS2, I don't think the extra 2.6 stuff in its version of avisynth_c.h was preventing it from autoloading, since I experimented with it a little last night using Meld to merge the changes in locally, and it still didn't autoload. So it seems the problem lies elsewhere (although having avisynth_c.h get updated would be nice).
ultim
3rd October 2013, 07:41
...
The cache idea was mostly thought up to avoid that scenario, since it would store the names and plugin locations of the functions and avoid having to perform those first two steps and any instability that could cause - instead, it'd read the cache, compare it to the script, and then load only the plugins used in the script.
...
Ah, now I understand. So you mean a separate cache instance per script. Yes, that should work, and makes sense as long as the cache format is chosen so that it is easily editable by the user. The problem I see though, is that the cache would need to be regenerated each time the contents of plugin folders are changed, including non-plugin files. Even if the script has not changed. This equals to rescanning all the plugins, we don't have to execute code from all of them though, only in new or changed files.
Regarding FFMS2, I don't think the extra 2.6 stuff in its version of avisynth_c.h was preventing it from autoloading, since I experimented with it a little last night using Meld to merge the changes in locally, and it still didn't autoload. So it seems the problem lies elsewhere (although having avisynth_c.h get updated would be nice).
I didn't have time yesterday again, so all I could manage was to verify that the precompiled 2.17 Cplugin works (as a Cplugin, ofc). It works. Today I'm gonna recompile the cplugin from latest git and see what's the situation with that.
qyot27
3rd October 2013, 08:33
I didn't have time yesterday again, so all I could manage was to verify that the precompiled 2.17 Cplugin works (as a Cplugin, ofc). It works. Today I'm gonna recompile the cplugin from latest git and see what's the situation with that.
Could it have to do with the dual handling of 2.5 and 2.6 (even though that's present in 2.17 also)? The C-plugin explicitly has a 2.5 mode and a 2.6 mode. You can see this in action by throwing FFmpeg into gdb and using a script using FFMS2 with either 2.5.8 or 2.6 - the language changes in the debug messages.
With the latest 2.6 MT (the video file being served in was 10-bit 4:4:4 H.264):
(gdb) r -i test.avs
...
libpostproc 52. 3.100 / 52. 3.100
Error while mapping shared library sections:
`C:\WINDOWS\system32\avisynth.dll': not in executable format: File format not recognized
warning: FFMS2 avs plugin: Initializing...
warning: FFMS2 - avs 2.6 mode
Guessed Channel Layout for Input Stream #0.1 : stereo
Input #0, avisynth, from 'test.avs':
Duration: 00:05:00.47, start: 0.000000, bitrate: 0 kb/s
Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p, 848x480, 23.98 fps, 23.98 t
br, 23.98 tbn, 23.98 tbc
...
vs. 2.5.8:
(gdb) r -i test.avs
...
libpostproc 52. 3.100 / 52. 3.100
warning: DllMain: hModule=0x10000000, ulReason=1, lpReserved=0x00000000, gRefCnt = 0
warning: FFMS2 avs plugin: Initializing...
warning: FFMS2 - avs 2.5 mode
Guessed Channel Layout for Input Stream #0.1 : stereo
Input #0, avisynth, from 'test.avs':
Duration: 00:05:00.47, start: 0.000000, bitrate: 0 kb/s
Stream #0:0: Video: rawvideo (BGRA / 0x41524742), bgra, 848x480, 23.98 fps, 23.98 tbr,
23.98 tbn, 23.98 tbc
...
I'm fairly sure I'm still using the same build I posted here, if it helps:
http://forum.doom9.org/showthread.php?p=1643738#post1643738
But building right from git would work, too. All the changes to the c_plugin branch after that build were for Linux/OSX (and the currently-disabled HEVC tag).
ultim
3rd October 2013, 08:55
I can't quite remember *when* 2.17 was tagged, but I'm thinking it probably was from right before it gained the dual 2.5/2.6 handling. The C-plugin explicitly has a 2.5 mode and a 2.6 mode. You can see this in action by throwing FFmpeg into gdb and using a script using FFMS2 with either 2.5.8 or 2.6 - the language changes in the debug messages.
Yes I noticed that some builds have dual interfaces, in my case C and 2.5. I made sure that the C interface of ffms2 was used by temporarily changing the interface load order in Avs+, and ffms2 loaded up and worked correctly with the C interface. That was 2.17 though.
I'm fairly sure I'm still using the same build I posted here, if it helps:
http://forum.doom9.org/showthread.php?p=1643738#post1643738
But building right from git would work, too. All the changes to the c_plugin branch after that build were for Linux/OSX (and the currently-disabled HEVC tag).
Oh, thx for the link. I'll just use that binary then instead of building it myself :)
qyot27
3rd October 2013, 09:04
Well, unfortunately, I think it's actually a problem with my computer. I went and tried the official 2.17-cplugin package, and it won't load either.
[avisynth @ 03792520] Script error: There is no function named 'ffindex'.
(C:/Program Files/AviSynth 2.5/plugins/FFMS2.avsi, line 32)
(test.avs, line 1)
test.avs: Unknown error occurred
or if I don't try to use FFMS2.avsi:
[avisynth @ 03792520] Script error: There is no function named 'FFVideoSource'.
(test.avs, line 1)
test.avs: Unknown error occurred
So something is going on that makes it fail, but I don't know what.
ultim
3rd October 2013, 19:35
I tried your build from http://forum.doom9.org/showthread.php?p=1643738#post1643738 , and it worked for me. If the problem on your computer is a missing dependency, depends.exe can help you diagnose what is wrong.
qyot27
3rd October 2013, 22:15
I don't think it's a missing dependency, because builds of the previous HEAD (BitBlt refactor) can load it, and looking at that build and the current HEAD in Dependency Walker show that the only three missing ones - EFSADU.DLL, IESHIMS.DLL, and WER.DLL - are missing from both of them. Did rewriting the plugin management bring in a new dependency?
I'm going to try running a Debug build and see if it catches anything.
qyot27
3rd October 2013, 23:10
I really can't figure out the MSVC debugger, but both DebugView and gdb picked up on the following when I tried to run a script with a Debug build of AviSynth+ in ffmpeg:
warning: DllMain: hModule=0x10000000, ulReason=1, lpReserved=0x00000000, gRefCnt = 0
warning: StringDump: Allocating new stringblock.
[avisynth @ 03792c00] Script error: There is no function named 'ffindex'.
(C:/Program Files/AviSynth 2.5/plugins/FFMS2.avsi, line 31)
(test.avs, line 1)
warning: StringDump: DeAllocating all stringblocks.
test.avs: Unknown error occurred
warning: DllMain: hModule=0x10000000, ulReason=0, lpReserved=0x00000000, gRefCnt = 0
Dunno if that helps.
I did try to bisect it, though, and the issue arises with the rewritten plugin management in 9567b94e. The commit immediately before it works. I'm going to see if it's okay on some of the other computers I have access to.
ultim
3rd October 2013, 23:18
Thx for your efforts. I'm debugging it right now too. I've narrowed down the problem onto the 2.5 interface not working with ffms2, but dunno yet why. Don't try it on other machines, it won't work either.
The reason it worked for me, is because to make sure that ffms2 will be loaded with the C interface (and not 2.5), I've changed the interface probation order on my computer. Loading ffms2's does really work then, and I'm 100% sure it does on your computer too.
The problem is, that the binary I've published searches for the Avs 2.5 interface before the C interface, and because ffms2 also has that, Avs+ will use that instead of the C interface. This is where things start to get interesting. The call is made to the AvisynthPluginInit2 function, but it never registers any functions. I see it in your sources that it should correctly call Env->AddFunction, yet during runtime those calls never get back to me. I still have to find out why.
ultim
3rd October 2013, 23:56
The problem seems to be in your build of ffms2. If I use TheRyuu's binary of 2.19 (the post right after yours in http://forum.doom9.org/showthread.php?p=1643738#post1643738), then it works perfectly. If I then overwrite ffms2.dll with your build r836, it stops working again.
Whatever the differences are in the source or compilation steps between your and TheRyuu's binary, it breaks your Avisynth 2.5 interface in ffms2.
qyot27
4th October 2013, 00:25
The problem seems to be in your build of ffms2. If I use TheRyuu's binary of 2.19 (the post right after yours in http://forum.doom9.org/showthread.php?p=1643738#post1643738), then it works perfectly. If I then overwrite ffms2.dll with your build r836, it stops working again.
Whatever the differences are in the source or compilation steps between your and TheRyuu's binary, it breaks your Avisynth 2.5 interface in ffms2.
The difference between them is that TheRyuu's build is the regular C++ plugin from the master branch, not the C plugin. The C plugin sources are in the src/avisynth_c directory (which only exists in the c_plugin branch), and completely ignores the src/avisynth directory since that's the C++ interface.
qyot27
4th October 2013, 00:51
And after experimenting with the checking order in avs_core/core/PluginManager.cpp, swapping the C and 2.5 checks, FFMS2 does indeed work. But then AssRender stops loading.
EDIT: Totally disregard the AssRender thing, I'd forgotten I'd moved it out of the plugins folder.
ultim
4th October 2013, 07:49
The difference between them is that TheRyuu's build is the regular C++ plugin from the master branch, not the C plugin. The C plugin sources are in the src/avisynth_c directory (which only exists in the c_plugin branch), and completely ignores the src/avisynth directory since that's the C++ interface.
Even if you say that the Cplugin-build completely ignores the other directory, an entry point for AvisynthPluginInit2 is still generated in the Cplugin, which makes Avs(+) think that it supports the C++ interface. I'd suggest removing that method (or at least not exporting it) in the C plugin build if it is officially not working anyway, to prevent Avisynth servers from trying to load that interface. Then everything will work.
Whether you remove the C++ entry point from the C build or not, I'm changing the loading order in my next public build. Meaning that the new order will be 2.6 -> C -> 2.5. Not just because of ffms2, I've already written in #74 (http://forum.doom9.org/showpost.php?p=1646392&postcount=74) (that was before you've mentioned your problem with ffms2) that this change should happen. ffms2 is just yet another reason. But I still think you should remove AvisynthPluginInit2 from the C-build if it is not intended to work anyway.
qyot27
4th October 2013, 12:04
It's true that the C plugin doesn't build anything from the src/avisynth directory, in that the GNUmakefile never refers to it. The reference to AvisynthPluginInit2 is in src/avisynth_c/avisynth.c, though, which is where all of this ends up getting caught.
The offending code block in question:
/* the AVS loader for LoadPlugin.
* Allows the conditional avs script logic:
* ( LoadPlugin("ffms2.dll") == "Use LoadCPlugin" ) ? LoadCPlugin("ffms2.dll") : NOP()
* to successfully load the plugin for both MSVC and MinGW versions */
const char * __stdcall AvisynthPluginInit2( void *Env )
{ return "Use LoadCPlugin"; }
So it would appear it was put in there for some sort of LoadPlugin trickery, but I can't see any reason for it either. I've removed it locally so that the C-plugin only uses the C interface init.
ultim
4th October 2013, 14:54
/* the AVS loader for LoadPlugin.
* Allows the conditional avs script logic:
* ( LoadPlugin("ffms2.dll") == "Use LoadCPlugin" ) ? LoadCPlugin("ffms2.dll") : NOP()
* to successfully load the plugin for both MSVC and MinGW versions */
const char * __stdcall AvisynthPluginInit2( void *Env )
{ return "Use LoadCPlugin"; }
Because Avisynth has been supporting both Cplugins and C++ plugins for a long time now, that piece of code doesn't look too meaningful for me either. Both MSVC and MinGW versions of ffms2 should be able to load using LoadCPlugin, so instead of writing that condition into a script, the script author could simply just use LoadCPlugin. I think that hack must be really old.
Anyway, with that removed, my previously posted binary build of Avs+ should load your ffms2 correctly now.
Gavino
4th October 2013, 14:55
/* the AVS loader for LoadPlugin.
* Allows the conditional avs script logic:
* ( LoadPlugin("ffms2.dll") == "Use LoadCPlugin" ) ? LoadCPlugin("ffms2.dll") : NOP()
* to successfully load the plugin for both MSVC and MinGW versions */
const char * __stdcall AvisynthPluginInit2( void *Env )
{ return "Use LoadCPlugin"; }
So it would appear it was put in there for some sort of LoadPlugin trickery, but I can't see any reason for it either.
It makes sense in vanilla Avisynth, as you can use the highlighted line in a script to load ffms2.dll regardless of whether you have the C++ or C version.
With ultim's build, that's not necessary (and actually goes wrong) since LoadPlugin and LoadCPlugin are the same thing.
ultim
4th October 2013, 15:38
It makes sense in vanilla Avisynth, as you can use the highlighted line in a script to load ffms2.dll regardless of whether you have the C++ or C version.
With ultim's build, that's not necessary (and actually goes wrong) since LoadPlugin and LoadCPlugin are the same thing.
AFAIK, vanilla Avisynth also has C-plugin support, so it doesn't seem to make sense to me, because instead of writing "( LoadPlugin("ffms2.dll") == "Use LoadCPlugin" ) ? LoadCPlugin("ffms2.dll") : NOP()" the script author could say "LoadCPlugin("ffms2.dll")" in both projects.
But more importantly, with these changes the plugin should now be able to load in both vanilla Avisynth and in Avisynth+.
Gavino
4th October 2013, 16:17
AFAIK, vanilla Avisynth also has C-plugin support, so it doesn't seem to make sense to me, because instead of writing "( LoadPlugin("ffms2.dll") == "Use LoadCPlugin" ) ? LoadCPlugin("ffms2.dll") : NOP()" the script author could say "LoadCPlugin("ffms2.dll")" in both projects.
But that won't work if the ffms2.dll you have is the C++ version. The point of using the conditional line in the script is that the user doesn't need to know which version he actually has if he loads it that way.
However, he could also use a try/catch instead and that would not require the extra code in the C plugin. The same script would then work in both Avisynth and Avisynth+. (In avs+, the try/catch would be unnecessary, but harmless).
ultim
4th October 2013, 16:48
But that won't work if the ffms2.dll you have is the C++ version. The point of using the conditional line in the script is that the user doesn't need to know which version he actually has if he loads it that way.
Ah, now I finally get it. I was assuming all the way through that the user would be using the Cplugin version of ffms2. Thx for making it clear to me.
As I said before, I'm gonna change Avisynth+ to try the C interface of a plugin before the 2.5 interface anyway. That will solve these problems too, and the user would be able to use both the C and C++ version of ffms2 with any of the two Avisynth projects, even if qyot27 decides not to remove those lines. I guess it is even better then if leaves those lines there, for the users who are using that hack.
qyot27
5th October 2013, 01:15
I actually did remove them, because the real need for that hack is only if ffms2.dll is not in the autoloading folder. The C-plugin (well, my builds of it) has long had LoadCPlugin("ffms2.dll") included in FFMS2.avsi, which handles it for classic AviSynth, and the C++ version would autoload on classic anyway. The inclusion of LoadCPlugin in FFMS2.avsi got merged into the main c_plugin branch after FFMS2 officially moved to git about a month ago.
I've not issued a pull request for it yet, so it's only in my personal FFMS2 repo.
TurboPascal7
6th October 2013, 08:53
Great job, ultim, I'm really happy to see someone not ancient working on avisynth.
What I would like to see is some kind of a roadmap. In a form of github issues or just a page in the wiki, but anything that would help developers start contributing would be really helpful. I assume x64 and multithreading support is planned in the (not near) future?
And two more questions:
1. What is the reason to keep compatibility with 2005 runtime when you can target XP with 2008/10/11 just fine (11 might be having some problems in wine though)?
2. What exactly breaks AvsPmod compatibility? This problem is really important since it renders the project useless for a lot of people.
jpsdr
6th October 2013, 10:02
I also be happy to see an x64 version, but from what i've understood, two big steps are needed.
1 - Remove all the inline asm and put it on external asm files.
2 - Rewrite these asm file to be x64 compliant.
The work already done in the already existant x64 version may help, nevertheless, it still seems to be a very big work...
TurboPascal7
6th October 2013, 10:10
I wouldn't mind helping rewriting the asm to intrinsics but I don't think I can handle external asm files for long (nor do I think it's reasonable but that's another question). That's the main reason I asked about vs2005 support - I'm not sure how good it is with intrinsics and using external asm might be the only option.
qyot27
6th October 2013, 11:22
I'd mentioned it in a PM, but AvxSynth (which can build and work on x64 just fine) did have asm disabled and replaced with regular C/C++ versions that could get re-used, although for all I know it may have just merged that stuff in from Avisynth64. From what I understand there was a push a couple years ago or so to convert the asm in AviSynth to x264ASM, which would result in separating the stuff out anyway. Not to mention cross-platform interests and the possibility of non-x86 CPU architectures.
On a different tangent, I'd prefer if there was a more project-specific setup on Github. It's a lot easier to remember, say, github.com/avisynthplus/avisynthplus.git than having it as simply a personal repo of avisynth as it currently is. For that matter, shouldn't the thread title also be changed now too?
vdcrim
6th October 2013, 12:03
2. What exactly breaks AvsPmod compatibility?
Just fixed in current git.
The $InternalFunctions$ and $PluginFunctions$ global vars are gone since the plugin management rewrite. Was that by mistake?
ultim
6th October 2013, 13:03
I will add issues to the Wiki to start with, and most probably I should also add a main README.md to the GitHub project so that visitors there get some more information other than the dump of a repository.
Right now I'm still looking at exception usage in Avisynth, continuously doing smaller cleanups and refactorings. I've also started to add Gavino's scripting extensions to Avisynth+, but I had to ask him because GScript and Avisynth have slightly different licensing terms. Fortunately he is completely okay with the integration (I've just received reply), so I can continue with that. I've also spent some time since the last release inspecting alternatives to the current BitBlt, so let us hope that it will result in a slight performance improvement. If there will be any, it won't be large, but at least it will be uniform (not specific to certain plugins or scripts).
Adding good threading is on the top of my wish-list too, and I am trying to find ways. As of right now there are parts of the Avisynth code involved which I did not investigate fully yet (mostly related to caching), so first I need to figure that part out completely.
x64 support is also a goal, but certianly not for the near-future. As many of you have said, the greatest obstacle here are the pieces of inline asm. I must admit that I'm not very versed in x86 asm, so here too I will be counting on your help.
1. What is the reason to keep compatibility with 2005 runtime when you can target XP with 2008/10/11 just fine (11 might be having some problems in wine though)?
It is more like, there is no reason to drop its support yet. Right now the most I could use from later VS versions is support for the C++11 STL (shared/unique_ptr, atomic, threading), but these are only available in VS2012, so that would be too limiting. This is also the reason I'm considering adding Boost as a dependency, to not have to rely on VS2012 yet still be able to make use of these libraries.
2. What exactly breaks AvsPmod compatibility? This problem is really important since it renders the project useless for a lot of people.
To be able to specify autoload directories in scripts, I had to delay autoloading plugins to the latest point possible. (As a comparison, upstream Avisynth autoloads plugins as soon as the ScriptingEnvironment is initialized, way before any script is loaded.) The result is that, in Avisynth+, the list of plugin functions is not available until a script has been loaded, so for now I have removed exporting special variables like $PluginFunctions$, $Plugin!...!Param$ and $InternalFunctions$, because they didn't make too much sense with the modifications in place. I suspect AvsPmod tries to read these, which is where the conflict comes from.
The best way to solve this would be to (both needed)
- Make AvsPmod only read these variables once a script has been loaded (so that autoload directories that were specified in the script can be taken into account)
- and add the ability to Avisynth+ to force autoloading from the standard directories (to faciliate writing new scripts). This is easy to accomplish without extending the binary interface.
The above two points require modifications to both Avisynth+ and AvsPmod.
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.