Log in

View Full Version : Simple Compile Time Filter


jmac698
13th July 2012, 12:28
Example adds a new string function which does nothing but return the string.

#include <windows.h>

#include <stdio.h> // OutputDebugString(), Needs DebugView utility, http://technet.microsoft.com/en-gb/sysinternals/bb545027
#include "Avisynth.h"

// Helper function - exception protected wrapper, From Avisynth source, conditional.cpp
inline AVSValue GetVar(IScriptEnvironment* env, const char* name) {
try {return env->GetVar(name);} catch (IScriptEnvironment::NotFound) {} return AVSValue();
}

static AVSValue __cdecl ExtractStr(AVSValue args, void* /* userDataP */, IScriptEnvironment* envP)
{
const char* string = args[0].AsString();
const char* l = args[1].AsString();
const char* r = args[2].AsString();
const char* val = string;
return (val == NULL) ? AVSValue()
: AVSValue(envP->SaveString(val, strlen(val)));
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("ExtractStr", "[string]s[LeftDelimiter]s[RightDelimiter]", ExtractStr, 0);
return "ExtractStr 0.1";
}

That's pretty simple...
How would you return a float?
There is a missing atan2 function.

I also have no idea how to setup the C++ functions. Feel free to write the between delimiter extraction :)

I was thinking of using it like "tweak(2,3,3)","tweak(",")" and then another strtok type function. Then I can parse stuff. Why? First of all, to have a more flexible filereader. Also for building expressions like for masktools. Or for using string commands as part of your function.

TheFluff
13th July 2012, 12:35
float f = 0.5;
return AVSValue(f);
I think you can pass a double to the AVSValue constructor too, but it may be force-downcast to single precision later.

For atan2, #include <math.h> (http://www.cplusplus.com/reference/clibrary/cmath/atan2/).

For string processing, take a look at std::string in the C++ standard library (http://www.cplusplus.com/reference/string/).

I don't understand why you're calling this a compile-time filter nor why it deserves its own thread.

StainlessS
13th July 2012, 15:15
Jmac, From SDK, Non-Clip Sample:
http://avisynth.org/mediawiki/Filter_SDK/Non-clip_sample

EDIT: The second fn is almost identical to what I did for "Simple Runtime Filter",
Arh dang!

EDIT: 'RightDelimiter' in your AvisynthPluginInit2 does not have a type.
env->AddFunction("ExtractStr", "[string]s[LeftDelimiter]s[RightDelimiter]", ExtractStr, 0);

jmac698
16th July 2012, 04:20
Constructor code runs exactly once as the script compiles.

GetFrame code runs once per frame being generated.

The cache can stop GetFrame being run a second time for the same frame number.

http://forum.doom9.org/showthread.php?p=803193#post803193

So I think it's a compile time filter then.

The atan2 function is missing from Avisynth, not C, though there's an approxmation in avslib.

I didn't see a sample like this in the non-clip samples in the filtersdk that came with 2.58, but maybe the 2.6/wiki is more up to date.

Wilbert
16th July 2012, 19:12
The atan2 function is missing from Avisynth
No, it's not (at it's added recently, but i'm not sure whether it is in 2.60a3).

StainlessS
16th July 2012, 22:42
[url]
I didn't see a sample like this in the non-clip samples in the filtersdk that came with 2.58, but maybe the 2.6/wiki is more up to date.

See Non-clip Sample/Numeric function example,
as linked in my previous post:

http://avisynth.org/mediawiki/Filter_SDK/Non-clip_sample

Been there for donkeys years.

And just in case you missed my other edit:

'RightDelimiter' in your AvisynthPluginInit2 does not have a type.
env->AddFunction("ExtractStr", "[string]s[LeftDelimiter]s[RightDelimiter]", ExtractStr, 0);

TheFluff
17th July 2012, 14:33
http://forum.doom9.org/showthread.php?p=803193#post803193

So I think it's a compile time filter then.

I think you've misunderstood the post. IanB was most likely referring to the constructor of a class that inherits from GenericVideoFilter. Any function exported via env->AddFunction() can be called at any point during script compilation and/or at run-time. Any plugin and any script function can call any other function it wants at any point during which the execution passes through it. For example, if you export atan2() via an Avisynth plugin, you could write a plugin that uses env->Invoke() to call it during GetFrame() or whenever it wants.

The term "compile-time filter" is, in my opinion, confusing and doesn't really mean anything. All Avisynth functions can be called both during compilation and at runtime. Your example code isn't a filter either; it's a plugin that exports some string processing functions.

The term "run-time function" is likewise not very meaningful. The fact that most Avisynth non-filter functions are usually only called once during script compilation doesn't mean that you cannot call them at any other time, so all non-filter functions can de facto be used as run-time functions. Filters (i.e. Avisynth functions that return a clip) are somewhat special in that the environment calls their GetFrame() function when a new frame is requested, which in principle makes those too run-time functions since they do stuff at run-time.

jmac698
17th July 2012, 21:10
Hmm, one problem, why can I do this only once:

current_frame=0
luma=averageluma

TheFluff
18th July 2012, 19:08
Hmm, one problem, why can I do this only once:

current_frame=0
luma=averageluma


What?
(need some context here)

jmac698
19th July 2012, 07:42
http://forum.doom9.org/showthread.php?p=1513514#post1513514

http://forum.doom9.org/showthread.php?p=1513774#post1513774


This is basically a 'cheat' I worked out based on the internal workings of the run-time environment. Filters like ScriptClip set current_frame for each frame rendered at run-time and the value is used by functions like AverageLuma and YPlaneMin to know which frame to operate on. By setting current_frame manually, these functions (intended to be used only at run-time) can be made to return the value for a specific frame at compile-time instead of giving an error.

Strictly, this is cheating as it relies on the internal workings of Avisynth which could in principle be changed in the future.


I think what compile-time filter means, is not that you can't call it at any time, but that it can't update it's value any further, from a video frame, in this case. You can think of compile-time and runtime as two passes on a video, and the deleteframes script makes use of this concept.
You can do a pass to read some conditions of the frames in the first pass (which causes a long startup time), and then act on those conditions at runtime.
I'm pretty sure there's some kind of difference here.

TheFluff
19th July 2012, 18:15
I think what compile-time filter means, is not that you can't call it at any time, but that it can't update it's value any further, from a video frame, in this case. You can think of compile-time and runtime as two passes on a video, and the deleteframes script makes use of this concept.
You can do a pass to read some conditions of the frames in the first pass (which causes a long startup time), and then act on those conditions at runtime.
I'm pretty sure there's some kind of difference here.

There is no difference. You could, if you wanted, call a function that requires current_frame to be set "a run-time function", but there's really nothing that makes that function special or different from any other function, from the environment's perspective. There's nothing that stops you from writing a recursive function that sets current_frame sequentially from 0 to framecount()-1 and calls that filter once for every frame in the video at compile time. During script compilation, the environment will call the function you've exported via env->AddFunction as many times as required, with the appropriate context each time. If it's returning unexpected results (like the same result each time), there's either a bug in the function or you're doing something wrong.

Likewise, any "compile-time function" can be called at runtime using scriptclip etc. If you want to pass the current frame as an argument to the function, you may have to do some clever stuff (probably just pass it as a 1-frame clip), but again there's nothing that makes the function special from the environment's perspective. There's also nothing that makes the function return the results it happened to return at compile-time, either.

Gavino
21st July 2012, 10:35
How would you return a float?
There is a missing atan2 function.
As Wilbert says, atan2 has been added in the latest cvs.
However, some time back I provided a version here (at your request :)).
This includes source code, so you can see how to return a float.

jmac698
21st July 2012, 10:42
I completely forgot about that somehow, I'm sure I've used it!