Log in

View Full Version : Question about Scope of Variables


blaze077
12th October 2016, 06:30
Can a run-time filter change the value defined for a variable in the top-level script?

The following code does not change the value of x from 5 to 6.
BlankClip(length=240, width=640, height=480, pixel_type="RGB32", fps=24, fps_denominator=1, audio_rate=44100, channels=1, sample_type="16bit", color=$000000)
x = 5
FrameEvaluate("x = 6", show=false, after_frame=false)
Subtitle(String(x))

And can a run-time function pass a global variable?

The following code does not define a value for x.
BlankClip(length=240, width=640, height=480, pixel_type="RGB32", fps=24, fps_denominator=1, audio_rate=44100, channels=1, sample_type="16bit", color=$000000)
FrameEvaluate("global x = current_frame")
Subtitle(String(x))

Thank you.

Gavino
12th October 2016, 08:41
Can a run-time filter change the value defined for a variable in the top-level script?
Yes, but the change naturally occurs at run-time.

In your examples, the argument to Subtitle is evaluated at compile-time, before the run-time filter does the assignment.
See The script execution model/Sequence of events (http://avisynth.nl/index.php/The_script_execution_model/Sequence_of_events).

blaze077
12th October 2016, 19:20
That makes sense. Thank you.

blaze077
13th October 2016, 02:07
Sorry if this is asking the same thing as before but if the run-time filter is evaluated after the other filters, then in this script:

BlankClip()
x = "black"
ScriptClip("""x="white" Subtitle(x)""")
Subtitle(x)

Why does the final output have "black" on top of "white" instead of the opposite?

Gavino
13th October 2016, 09:25
if the run-time filter is evaluated after the other filters, then in this script:
...
Why does the final output have "black" on top of "white" instead of the opposite?
The run-time script [x="white" Subtitle(x)] is evaluated after the main script, and this evaluation happens each time ScriptClip() is asked to produce a frame. However, this does not change the order of the filter chain itself, which is:
BlankClip() -> ScriptClip() -> Subtitle()

So after ScriptClip() has produced a frame with a white subtitle, the frame is passed on to the final Subtitle() and has a black title superimposed. (Black because the argument to that Subtitle() is evaluated only once, at compile-time)

blaze077
13th October 2016, 21:11
Got it. Thank you.

blaze077
2nd March 2017, 04:25
I, again, have a question. Is there any way to use values from AverageLuma(), YDifferenceFromPrevious() etc. outside ScriptClip(), FrameEvaluate() etc.? Let's say I want to perform a simple lut expression using AverageLuma. Is it possible to do this outside ScriptClip()?
avgluma = *some function that returns the value from AverageLuma()*
mt_lut("x " + String(avgluma) +" *")

StainlessS
2nd March 2017, 04:46
The problem is, you do not have a current frame to test, only exists in runtime filter.
You can do something like (fake current_frame)

current_frame=42
x=c.AverageLuma

where c has already been established as a clip.
v2.6 also has some arg (cant remember name, off-hand) that allows test of frame relative to currrent_frame,
in RT_stats, I use term Delta for the same thing. In RT, can supply frame to 'n' arg, which is same as setting current_frame fake variable.
[EDIT: Delta equiv name in 2.6 is Offset I think] [EDIT: Also can use in Grunt methinks]

Your example, would only work outside of runtime environment, if setting current_frame at every frame, otherwise, how would it know what frame
you require testing.

eg, something like below is recommended

SSS=""" # ScriptClip etc auto set current_frame, at every frame before this SSS ScriptClip script is executed.
avgluma=AverageLuma() # implicit use of current_frame
# avgluma=RT_AverageLuma() # Same result, implicit use of current_frame
# avgluma=RT_AverageLuma(n=current_frame) # Same result, explicit use
# avgluma=RT_AverageLuma(n=0, delta=current_frame) # Same result, this one not really recommended.
mt_lut("x " + String(avgluma) +"...")
retunn Last
"""

ScriptClip(SSS)

# Below would only execute once (just before frameserving starts, after ScriptClip constructor is called,
# functions and filter Constructors called pretty much in listing order),
# and apart from the one supplying n=27, would fail.

# avgluma=AverageLuma() # This would FAIL, no current_frame exists
# avgluma=RT_AverageLuma() # Same again
# avgluma=RT_AverageLuma(n=current_frame) # Same again
# avgluma=RT_AverageLuma(n=27) # OK so long a Last clip exists.




AverageLuma, is a function, not a filter, it only returns a single value once, if you want it to do it at every frame, then it must be called in runtime environment were it can be called at every frame. ScripClip etc, automatically set current_frame, at every frame and so that
is why it works as you would like (In runtime environment).

Filters MUST return a clip (frame by frame) so they can live and work in the frameserving time period, anything that does not return a frame/clip is not a filter (is function) and can only be called once unless called in runtime script where current_frame is auto set.

By the way, ScriptClip etc remove the special current_frame variable when exiting ScriptClip/etc, for some reason, one of the WriteFile type funcs actually sometimes set current_frame to -1 on exit (between frames), no idea why.



Hope some of that makes sense.

blaze077
2nd March 2017, 05:05
Got it. Thank you. :)

blaze077
26th March 2017, 00:14
I'm having trouble with debugging this function:
function DiffFunc(clip a, clip b, val "y", val "u", val "v"){
#Set default threshold for Y, U and V planes.
isInt(y) ? Assert((y >= 0), "Y must be positive") : NOP()
isInt(u) ? Assert((u >= 0), "U must be positive") : NOP()
isInt(v) ? Assert((v >= 0), "V must be positive") : NOP()
yPlane = (!(Defined(y)) || IsBool(y) && y) ? 2 : \
(IsBool(y) && !y) ? -1 : \
(isInt(y)) ? y : Assert(false, "Y must be a boolean or an int")
uPlane = (!(Defined(u)) || IsBool(u) && u) ? 2 : \
(IsBool(u) && !u) ? -1 : \
(isInt(u)) ? u : Assert(false, "U must be a boolean or an int")
vPlane = (!(Defined(v)) || IsBool(v) && v) ? 2 : \
(IsBool(v) && !v) ? -1 : \
(isInt(v)) ? v : Assert(false, "V must be a boolean or an int")
Assert(!(yPlane==uPlane==vPlane==-1), "You need to select at least one plane")
threshold = yPlane + uPlane + vPlane
a.GScriptClip("""
totalDiff = 0
yPlane >= 0 ? Eval("totalDiff+=LumaDifference(a, b)") : NOP()
uPlane >= 0 ? Eval("totalDiff+=ChromaUDifference(a, b)") : NOP()
vPlane >= 0 ? Eval("totalDiff+=ChromaVDifference(a, b)") : NOP()
totalDiff > threshold ? Subtitle("0") : Subtitle("1")
""", args="a, b, yPlane, uPlane, vPlane, threshold")
}
I'm using this script:
c = BlankClip(pixel_type="YV12")
DiffFunc(c, c)
And get the error:
Script error: syntax error
((null), line 1, column 11)
([ScriptClip], line 3)
Could someone point out what is wrong?

EDIT: I don't quite understand the "(null)" message as the values for all variables in args seem to be passed. Maybe it has something to do with the condition.

Thank you.

TheFluff
26th March 2017, 00:52
The error message was fairly clear, I thought? You only have one ScriptClip and while the (null) is a bit confusing, looking at line 3 you see an Eval() which seems pretty suspicious, and at position 11 in the string argument to that Eval() you have the equals sign of +=.

Avisynth script doesn't have C-like extended assignment operators (+=, -= etc).

blaze077
26th March 2017, 01:03
Got it. I did not understand what "(null)" meant as all values for the variables were passed to ScriptClip. I was confusing the null error for Eval with ScriptClip. Sorry and thank you.

TheFluff
26th March 2017, 01:25
Well, the context info should say "Eval", not "(null)". It got the string position right so it obviously knows what the context is, it's just not being reported correctly. There's probably a bug somewhere, either in GScript or in the Avisynth script parser.

StainlessS
26th March 2017, 01:48
This is (I think) same as original logic


function DiffFunc(clip a, clip b, val "y", val "u", val "v") {
#Set default threshold for Y, U and V planes.
y=Default(y,true) u=Default(u,true) v=Default(v,true) # identical to original script logic
isInt(y) ? Assert((y >= 0), "Y must be positive") : NOP()
isInt(u) ? Assert((u >= 0), "U must be positive") : NOP()
isInt(v) ? Assert((v >= 0), "V must be positive") : NOP()
yPlane = (y.IsBool ) ? ((y) ? 2 : -1) : (y.isInt) ? y : Assert(false, "Y must be a boolean or an int")
uPlane = (u.IsBool ) ? ((u) ? 2 : -1) : (u.isInt) ? u : Assert(false, "U must be a boolean or an int")
vPlane = (v.IsBool ) ? ((v) ? 2 : -1) : (v.isInt) ? v : Assert(false, "V must be a boolean or an int")
Assert(!(yPlane==uPlane==vPlane==-1), "You need to select at least one plane")
threshold = yPlane + uPlane + vPlane
# RT_DebugF("yPlane=%d uPlane=%d vPlane=%d threshold=%d",yPlane,uPlane,vPlane,threshold)
a.GScriptClip("""
totalDiff = 0
totalDiff = totalDiff + ((yPlane>=0) ? LumaDifference(Last, b) : 0)
totalDiff = totalDiff + ((uPlane>=0) ? ChromaUDifference(Last, b) : 0)
totalDiff = totalDiff + ((vPlane>=0) ? ChromaVDifference(Last, b) : 0)
totalDiff > threshold ? Subtitle("0") : Subtitle("1")
""", args="b, yPlane, uPlane, vPlane, threshold",Local=true)
}

c = BlankClip(pixel_type="YV12")
DiffFunc(c, c)


EDIT: Despite below looking a little odd, should work as intended.

Assert(!(yPlane==uPlane==vPlane==-1), "You need to select at least one plane")

blaze077
26th March 2017, 02:05
TheFluff: Thanks for your help. I think it is the Avisynth script parser as using vanilla ScriptClip or FrameEvaluate gives me that error.

Assert(!(yPlane==uPlane==vPlane==-1), "You need to select at least one plane")I was also not sure this would work but it seemed to work just fine.

Thank you, StainlessS, your code is definitely a better alternative than what I came up with. :)

StainlessS
26th March 2017, 02:11
That assert line explained in a few posts here:- https://forum.doom9.org/showthread.php?p=1783132#post1783132