Log in

View Full Version : Trouble using env->SetVar()


Kurosu
2nd July 2003, 21:27
In regard to AVSTimer thread, I'm trying to "export" a value (the last execution time for a particular timer) using env->SetVar() during GenericVideoFilter::GetFrame(...).

AVSValue out(Timer[index].temps / 10000.0);
env->SetVar(varname, out);

varname is a char * where the variable's name is stored, and which is passed as an argument to the filter. I verified that the string and the AVSValue were properly updated.

But when I try to use it:
- if I set this value before the call to the filter, it remains unmodified after its call
- if I don't set it, the value is still null

Here is the example string I used to test this:
SomeFilter(<someargs>,varname="time")
last.subtitle("I got time=" + string(time))

I plan to check ConditionalFilter, but, meanwhile, can somebody enlighten me on why it wouldn't work properly ?

[edit]
And I guess I can't simply create a function returning an AVSValue, because it will be evaluated only once...

Bidoche
3rd July 2003, 11:06
If i follow you correctly you were trying to get a value at parse time whose you only create and update at render time...

That ain't gonna work.

Kurosu
3rd July 2003, 12:35
Then, is it possible to have a variable continually reevaluated? ie not only at parse time?

ConditionnalFilter does it, but indeed the variable remains local to the filter, and the filter explicitly calls the evaluation, therefore that's not what I'm trying to achieve.

From reading the thread "3.0 news", I guess this was addressed...

Bidoche
3rd July 2003, 13:02
In 2.X it is possible to continually reavaluate env variables.
But of course their values are only usable at render, by another filter accessng the env with GetVar.

ConditionnalFilter does it, but indeed the variable remains local to the filter
And what prevent another filter to read this local var ?
Since you would be one writing both of them it shouldn't be a problem

From reading the thread "3.0 news", I guess this was addressed...3.0 is 3.0 and 2.X is 2.X.
I removed this facility in 3.0 since it was not really helpful...

Kurosu
3rd July 2003, 19:20
Originally posted by Bidoche
In 2.X it is possible to continually reavaluate env variables.
But of course their values are only usable at render, by another filter accessng the env with GetVar.

OK, therefore, I can't do what I expected (see the pseudo-script in my first post).


And what prevent another filter to read this local var ?
Since you would be one writing both of them it shouldn't be a problem

Yes, I can't expect people to write their own filter so as to retrieve the value. And most operations are evaluated during parsing, so there seems to be no easy solution.


3.0 is 3.0 and 2.X is 2.X.
I removed this facility in 3.0 since it was not really helpful...
Well, it *would* have been helpfull... But not used enough to be worth the trouble to implement it (as you checked in the above mentionned thread). :D

Thanks for the replies.

sh0dan
3rd July 2003, 19:29
People should be able to retrieve the values using scriptclip/frameevaluate/conditionalfilter - but not before.

Doesn't:

timer = 0 # Initialize for first frame just in case.
avisource()
starttimer()
somefilter()
stoptimer(storeinvar="timer")
scriptclip("Subtitle(string(timer))")

work?

Kurosu
3rd July 2003, 20:46
Yes, this worked perfectly... And in my further tests it did no longer (but that's entirely my yet unidentified fault). As it isn't that important, I'll move on the next step.

But concerning my problem (that you have perfectly identified :) ), there seems to be one thing lacking. Check that function and suppose it's always evaluated (not only on parsing):

temp1 = 0.0
temp2 = 0.0
temp3 = 0.0
temp4 = 0.0
temp5 = 0.0

function myaverage(clip clip, float time)
{
temp1 = temp2
temp2 = temp3
temp3 = temp4
temp4 = temp5
temp5 = time
clip.scriptclip("Subtitle(string((temp1+temp2+temp3+temp4+temp5)/5)")
}

It seems to me that you can't manipulate the values directly. Is scriptclip able to do that work? I don't know, and would think no. Therefore, it would be very good to have one function (but as variable manipulation was removed in AVS3.0, it may only be used with AVS2.X) like:

bc("temp1=temp2; temp2=temp3; temp3=temp4; temp4=temp5; temp5=time; \
average=(temp1+temp2+temp3+temp4+temp5)/5")

which would evaluate on each call the environment variables? It's very feasible I guess, as ConditionFilter shows it (yet I don't know how to parse the string), except for the semicolon to mark a new operation.

As said about the removal of SetVar and GetVar from AVS3.0, it is probably not worth the trouble. I'll however consider writing it if I manage to understand how conditionalfilter works on that matter and if it's the only way to have such a function.

I guess the fact most opeartions are evaluated on script parsing explains the fact functions either returns a clip or nothing (or am I wrong?).

[edit]
To fit the text into the available space for display.

sh0dan
3rd July 2003, 22:15
What if you replace bc with FrameEvaluate? :)

It does the evaluation on each frame and passes the frames untouched.

Reminds me, that I should do some docs on wheter the evaluation is done before or after the filter above have been called. IIRC is is always done BEFORE the filters above are called.

Kurosu
3rd July 2003, 22:25
Originally posted by sh0dan
What if you replace bc with FrameEvaluate? :)

It does the evaluation on each frame and passes the frames untouched.
Ah! Nice "trick"! Then I guess nothing prevents you from doing your own computations concerning timings, provided the filter writes into the proper variable.


Reminds me, that I should do some docs on wheter the evaluation is done before or after the filter above have been called. IIRC is is always done BEFORE the filters above are called.
Yes, definetely, those functions were completely mysterious to me.

Bidoche
3rd July 2003, 22:34
Well, it *would* have been helpfull... But not used enough to be worth the trouble to implement it (as you checked in the above mentioned thread).You would still have to use a filter to update them and a filter to use them.
So for just pass values between filters, it's just as easy to pass values between filters...
And it avoids the risk of nasty var names collisions you are otherwise bound to meet the day an evil scripter decide to use your filters 10 times at once...

And for the var manipulation issue, 3.0 allows functions to be passed as values, it should address that.

Kurosu
3rd July 2003, 22:52
However, it seems one needs to somehow create variables by first declaring them, because the parser will not know they exist. Would it be worth to add a env->AddVar(const char *var, int type) (only usable at filter instanciation) in order to instruct the parser that if it encounters the previously added string, it is a variable of a particular type ?


@Bidoche / Sh0dan
Could the fact Get/SetVar() aren't available anymore in AVS3.0 breaks the way ConditionalFilter and associated functions? (I know most filters will have to be rewritten).

Bidoche
4th July 2003, 00:19
Why would the parser need to know of variables who exist only at render time ?

Could the fact Get/SetVar() aren't available anymore in AVS3.0 breaks the way ConditionalFilter and associated functions? (I know most filters will have to be rewritten). It should work more or less the same, but syntax will change, since you won't be passing a string interpreted by ConditionalFilter but a function it will use to make its decisions.
All the functions sh0dan created will be just regulars avisynth functions (operating on frames but 3.0 allows it)

The major change is it won't use final variable values anymore but bind the current ones.
But personaly, I more see this 'feature' as an unwanted side-effect, so I think the loss is not one.

Kurosu
4th July 2003, 00:46
Originally posted by Bidoche
Why would the parser need to know of variables who exist only at render time ?
If it isn't needed, then I guess I need to call env->SetVar() in the instanciation of the filter, so as to force the parser to acknowledge its existence. When the rendering occurs, variable is already set.

But then, appears a problem: if FrameEvaluate is called for frame n, it will use a variable which was set at frame n-1 by a filter higher in the reverse-order filter chain. Indeed, this is getting tricky...

Maybe I should request frame 0 in constructor, and then always prepair frame n+1 when frame n is being evaluated (but that won't work in non-linear access)...

Bidoche
4th July 2003, 09:53
I don't understand a thing about variables needing to be set before used...

Kurosu
4th July 2003, 10:22
Originally posted by Bidoche
I don't understand a thing about variables needing to be set before used...

Here's my point with this script:

#To make it work, I need to uncomment next line
#time=10.56
SomeFilter(<someargs>,varname="time")
subtitle("I got time=" + string(time))


When the script is being parsed, I will be told that it doesn't know what "time" is. I therefore have to declare it in some way:
- Initialize it in the script by writing at the begining of the script "time=10.35" (the purpose being to create that variable in the environment, not to set it!)
- Have something in the constructor of the GenericVideoFilter class used by SomeFilter (call it SomeFilter::SomeFilter(<args>) to create the environment variable time

The goal is that following references to the variable time (namely, the subtitle call) know what time is.

Of course, the 1st possibility is the simplest way to do.

Bidoche
4th July 2003, 11:32
Ok I finally get it :)


- Have something in the constructor of the GenericVideoFilter class used by SomeFilter (call it SomeFilter::SomeFilter(<args> ) to create the environment variable time That won't work, parsing is fully completed before any filter constructor is called.

Avisynth works in 3 times :
- parse time : parser compiles the script in a expression graph.
- execute time : execution of the expression graph, the program to create our video, it creates (if no errors) the filter graph
- render time : filter graph is being rendered

Constructors are being called at step 2, after parser would have complained about "time"


In fact, you are trying to use a variable to do the work of a function(not your fault, 2.x offer no alternative (or can it ?))
time should be a function who takes directly the value from the Somefilter filter and everything would be simpler.