Log in

View Full Version : Implement not filter, but function


dum
22nd November 2007, 00:38
Guys, tell me please, is it possible (using C++) implement not filter, but just a function, which will return not a clip, but something different: string or integer?

If it is - please tell me how: just point me, how to approach this.

foxyshadis
22nd November 2007, 04:25
Return an AVSValue from the constructor instead of a PClip. A lot of conditional filters are like that, or you can look at, say, the filters in script.cpp in the avisynth source.

Fizick
22nd November 2007, 06:00
there is no plugin example. So, dum, please tell to us when you finish :)

dum
23rd November 2007, 03:43
Return an AVSValue from the constructor instead of a PClip. A lot of conditional filters are like that, or you can look at, say, the filters in script.cpp in the avisynth source.

What dp ypu mean as "return from the constructor"? I do not have a lot of variants, what yo return :) Or you mean creation function like AVSValue __cdecl Create_Filter(AVSValue args, void* user_data, IScriptEnvironment* env)? Where to return then?

And how "script.cpp" can help me? Can you, please, show the exact place to me?

Thank you beforehand.

foxyshadis
23rd November 2007, 06:35
Here's a sample from script.cpp, edited for external use:

AVSValue Sin(AVSValue args, void* user_data, IScriptEnvironment* env) { return sin(args[0].AsFloat()); }

extern "C" __declspec(dllexport) const char* __stdcall
AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("sin", "f", Sin, 0);
return "sin";
}

You don't even need a class/constructor, come to think of it. Include avisynth.h and that could be a whole plugin right there. (If not a terribly useful one.)

dum
23rd November 2007, 16:11
Thank you.

And for each instance of AviSynth each own instance of plugin will be loaded?
The reason of this question is following - if I have to return string I need to allocate it somewhere else, except the local variable. Now I'm acting like this:

char p[200];

AVSValue Filter(AVSValue args, void* user_data, IScriptEnvironment* env)
{
...
strcpy(p,...);
return p;
}

What will be the most correct solution of such problem, which will keep me away from all probles with multiple instances etc?

dum
23rd November 2007, 17:09
I'm sorry: and there is completely no documentation (I mean, full description or something) for developers, except some commented samples?

tsp
23rd November 2007, 18:48
http://avisynth.org/mediawiki/Filter_SDK

dum
23rd November 2007, 19:31
Thanks, I got, concerning strings, but, nevertheless is it true that for each instance of AviSynth each own instance of plugin will be loaded? So can I leave data in the variable and rely that it will save it till next call?

IanB
23rd November 2007, 22:24
return env->SaveString(p);

See also Start->Programs->"Avisynth 2.5"->"FilterSDK Information" (it's an optional install with Avisynth).

stickboy
25th November 2007, 04:57
http://forum.doom9.org/showthread.php?t=130383

Anyway, a number of my plug-ins have functions that don't return clips, so you can use them as examples.

Fizick
25th November 2007, 12:22
I made several attempts to write non-clip plugin function without success. :( So, I created tutorial how to write non-clip function and placed it to FilterSDK.
http://avisynth.org/mediawiki/Filter_SDK/Non-clip_sample

He who can, does. He who cannot, teaches. :)
George Bernard Shaw, Man and Superman (1903) "Maxims for Revolutionists" http://www.quotationspage.com/quote/290.html

wonkey_monkey
24th July 2015, 16:58
An 8 year bump, but this seemed to be the most appropriate place to ask.

The example given in this thread is of a plugin that returns a float value, although the actual return type of the function is declared as AVSValue. Does this mean, then, that any variable declared in an AviSynth script is, fundamentally, an AVSValue?

Is there any way with env->AddFunction to create a function that takes an AVSValue (regardless of whether it may really be a string, int, float, or clip) as an input parameter? I can think of scenarios where this would be useful.

Secondly, is a string stored as an AVSValue a null-terminated one?

Gavino
24th July 2015, 19:51
Does this mean, then, that any variable declared in an AviSynth script is, fundamentally, an AVSValue?
Yes, that's right.

Is there any way with env->AddFunction to create a function that takes an AVSValue (regardless of whether it may really be a string, int, float, or clip) as an input parameter?
Use "." as the parameter character (instead of "s", "i", "f" or "c").
It will then accept an AVSValue of any underlying type.

is a string stored as an AVSValue a null-terminated one?
A string passed as a parameter from a script is an AVSValue.
Use AsString() to get a pointer to the contained null-terminated string.

wonkey_monkey
24th July 2015, 22:15
Thanks Gavino!


A string passed as a parameter from a script is an AVSValue.
Use AsString() to get a pointer to the contained null-terminated string.

What I meant was, could I make an AVSValue out of a non-null-terminated string (like, I think, a C++ String, as opposed to a C string?) - my plan is to pass arbitrary data around as AVSValue strings, but I'd need to be able to create strings which include 0 bytes.

For example, say I have a pointer (void*) to a block of data (could be floats, ints, anything - my code will know what to do with it later), and I know the number of bytes. Can I turn that into a single AVSValue that can be returned by a plugin function and assigned to an in-script variable, either as a string (in which case I'd still need to get it back as a block of data plus number of bytes later) or in some other fashion?

Gavino
25th July 2015, 00:04
In principle, you could get away with it by passing your void* pointer to the AVSValue(const char*) constructor.
But things would go horribly wrong if anything in the script tried to treat the thing as a string, as it would be expecting it to be null-terminated.

TheFluff
25th July 2015, 00:22
What I meant was, could I make an AVSValue out of a non-null-terminated string (like, I think, a C++ String, as opposed to a C string?) - my plan is to pass arbitrary data around as AVSValue strings, but I'd need to be able to create strings which include 0 bytes.

For example, say I have a pointer (void*) to a block of data (could be floats, ints, anything - my code will know what to do with it later), and I know the number of bytes. Can I turn that into a single AVSValue that can be returned by a plugin function and assigned to an in-script variable, either as a string (in which case I'd still need to get it back as a block of data plus number of bytes later) or in some other fashion?
just do what everyone else does and treat NewVideoFrame as if it was malloc and put your arbitrary data there

or don't, and use a frameserver that actually supports passing arbitrary data around instead of insisting on using a tool that makes every problem look like a nail

StainlessS
25th July 2015, 14:51
David, some RT funcs where using video frame as storage (as suggested by TheFluff above).


*****************************************************
******************* WEIRD FUNCTIONS *****************
*****************************************************

RT_FloatAsRGBA(float)
Given a float arg, returns an int formatted as for use as a color to eg BlankClip.
Can later be recovered from that clip using RT_RGB32AsFloat().

***
***
***

RT_RGB32AsFloat(clip,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0)
Compile/Runtime clip function.
Given an RGB32 clip that had a pixel value created via RT_FloatAsRGBA(), gets that pixel and returns as the
original float given to RT_FloatAsRGBA. By creating single pixel clips and stacking them horizontally/vertically,
you can use a frame as a two dimensional array of float, perhaps use the frame number for a third dimension.

***
***
***

RT_RGB32AsInt(clip,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0)
Compile/Runtime clip function.
Given an RGB32 clip that had a pixel value created from an Int, gets that pixel and returns as the
original Int. By creating single pixel clips and stacking them horizontally/vertically,
you can use a frame as a two dimensional array of Int, perhaps use the frame number for a third dimension.

Rip out from source if of use.

Alternatively, you could perhaps use RT array (or DBase) for storage, it has type BIN (8 bit unsigned char [EDIT: returned as int 0-255]) and array size
can be up to about 2GB single dimension array of BIN.
Or, write your own file based data storage that could be accessed via self written run time funcs and also much faster for use in some kind of
frame processing CPP func.

EDIT: You would want some kind of header to ID as your own format BIN data, and offset via header size to access BIN data.

wonkey_monkey
25th July 2015, 23:17
Thanks StainlessS.

Actually I am currently using clips as storage (with header IDs :) ) but I find it a little unsatisfactory as it seems unnecessarily abstract and open to accidental corruption.

I will experiment with AVSValues (which will give me their own headaches, I'm sure) with Gavino's information and see what can be achieved.

StainlessS
26th July 2015, 17:43
See also here (two page thread):- http://forum.doom9.org/showthread.php?t=165363&highlight=user_data+AddFunction
(EDIT: mainly 2nd page)

I've never actually used user_data for anything, could be used to allocate mem before AddFunction and pass as arg a pointer to your memblock,
would need to use the Avisynth AtExit function to release mem when Avisynth closes down.

Here the AddFunction used to add script function to Avisynth, user_data in blue:

env->AddFunction("RT_TimerHP","",RT_TimerHP, 0);



AVSValue __cdecl RT_TimerHP(AVSValue args, void* user_data, IScriptEnvironment* env) {
return RT_TimerHP_Lo(); // Implicit type conversion to AVSValue float
}


Some links:
user_data
http://forum.doom9.org/showthread.php?t=165363&highlight=user_data+AddFunction

AtExit
http://avisynth.nl/index.php/Filter_SDK/Non-clip_sample

I am yet to see any good example that uses user_data, if you do choose to try out then post as would be fairly unique example for others and wiki.

#############

env->SaveString:- http://avisynth.nl/index.php/Filter_SDK/Env_SaveString

is written somewhere (in docs) that memory returned as string from plugin could be used by coder as general storage so long as
you do not overrun allocated size, so could eg assign buffer to static pointer, and use other functions to access same pointer to
edit/return contents, a bit dodgy looking but would work.

wonkey_monkey
26th July 2015, 18:10
I am yet to see any good example that uses user_data, if you do choose to try out then post as would be fairly unique example for others and wiki.

I actually made use of user_data for the first time just a few days ago, by bundling together some very similar (and code-sharing) functions - they have different script names and different input parameters but all create an instance of the same class (with parameters rearranged/defaulted in different ways). user_data tells the class which of the operations to actually perform.

raffriff42
26th July 2015, 18:41
What I meant was, could I make an AVSValue out of a non-null-terminated stringNaive way:
Replace nul with "\\0"
Store as C string
Recall value at a later time
Replace "\\0" with nul.

This will generate more problems. Don't do it. Use a Binary-to-text_encoding (https://en.wikipedia.org/wiki/Binary-to-text_encoding) format such as base64 or uuencode. Whichever is supported in your current environment. No embedded nulls, problem solved. Especially for small amounts of data (< 16?KB)

StainlessS
26th July 2015, 18:50
Further to Gavino info

# Argument type specifier strings.
c - Video Clip
i - Integer number
f - Float number
s - String
b - boolean
. - Any type (dot)
# Array Specifiers
i* - Integer Array, zero or more
i+ - Integer Array, one or more
.* - Any type Array, zero or more
.+ - Any type Array, one or more


Also here some 'meanderings' concerning passing variable number of args (eg Polygon)
http://forum.doom9.org/showthread.php?p=1582201#post1582201

EDIT: In linked post, I suggested that max array size might be 64 (seen something like that in source) but is false,
I have used 256 sized array in ClipClop() without problems.

If passing AVSValue to a 'lower level' function (something I do a lot to allow use in internal routines), then suggest
use eg 'const AVSValue &avs', ie reference to an AVSalue as function parameter, that is an array of AVSValues, instead of copying
all on to stack, saves out-of-stack errors sometimes.

EDIT: Array size

const AVSValue& Rx;

numClips=Rx.ArraySize();

for(int i=0,i<numClips;++i) {
rClips[i] = Rx[i].AsClip();
}