Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
|
|
Thread Tools | Search this Thread | Display Modes |
3rd June 2008, 22:22 | #1 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Problems using AverageLuma etc in user-defined function
Why can't I use a run-time function (like AverageLuma) inside my own function, as long as my function is only called inside a run-time script (eg via ScriptClip)? Why doesn't this work:
Code:
function AL(clip c) { Subtitle(c, string(AverageLuma(c))) } ... ScriptClip("AL()") Code:
ScriptClip("Subtitle(string(AverageLuma()))") It's clear that run-time functions can only be used inside a run-time script. But here the call to function AL is inside the run-time script. I also understand the distinction between parse-time and run-time, which is usually at the root of problems with ScriptClip and friends. But here both the failing script ("AL()") and the working one ("Subtitle(...)") are at the same level. Is it a bug, or a feature, or is my code wrong? |
4th June 2008, 20:06 | #2 | Link |
Registered User
Join Date: Sep 2005
Location: 100011110010001000001 10000011111111000001
Posts: 221
|
This is because runtime variables and functions are made available at the top-level runtime script code only and not in nested scopes (thus they are effectively locals and not globals). Thus although "AL()" and "Subtitle(...)" are at the same level, the AverageLuma call inside your function is not. It is in a nested local scope and not the top-level (local) script scope.
It may not be intuitive, but this is the way things work ; the runtime environment is different from the "normal" script environment.
__________________
AVSLib, a free extension library for Avisynth. Current version: 1.1.0 (beta), 14/05/2007. [ Home page | Download page ] |
4th June 2008, 21:30 | #3 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Thanks gzarkadas, I understand what you are saying.
Do you know if there is a good reason that it has to work that way, or is it "just the way it is"? For usability, it would be advantageous to allow their use in functions called from within the run-time script. For my simple example it doesn't much matter, but for large/complex run-time scripts, it would make for more readable and maintainable code. Or would there be undesirable consequences that I am not foreseeing? (Maybe this is now really a question for the development forum?) |
5th June 2008, 23:22 | #4 | Link | |
Registered User
Join Date: Sep 2005
Location: 100011110010001000001 10000011111111000001
Posts: 221
|
Quote:
Now, about the reason, I can only speculate, since I am not an AviSynth developer , but I see the following difficulty if the choise were made to let runtime filters setting runtime variables at the global scope: The user script is allowed to do anything inside the very one GetFrame call that has set current_frame. This includes calling other runtime filters with different frame number(s).Using local scopes avoids this interaction; and now that I can step back and see my speculation in its entirety, I must admit that there is a good reason .
__________________
AVSLib, a free extension library for Avisynth. Current version: 1.1.0 (beta), 14/05/2007. [ Home page | Download page ] |
|
6th June 2008, 00:45 | #5 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Thanks for your very comprehensive reply.
I need to study your argument at greater length, but it strikes me that the restriction results from the specific way the run-time features are implemented 'under the hood', rather than something inherent in the concept. (That's still a 'good reason' if it's really just too hard to do it any other way.) |
6th June 2008, 10:46 | #6 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
If I understand gzarkadas correctly, he is saying:
But in any case, could this not be fixed just by ScriptClip resetting current_frame to its initial value when it exits GetFrame (just like it does with last)? current_frame could then be allowed to be global, and we could have access to it (and hence AverageLuma etc) in user functions. |
6th June 2008, 19:58 | #7 | Link | ||
Registered User
Join Date: Sep 2005
Location: 100011110010001000001 10000011111111000001
Posts: 221
|
Quote:
Quote:
The critical point is that the runtime environment has a different, event-driven model than the "normal" script flow. The script execution model page at the Avisynth wiki may be helpful on this. In summary:
Now, to return in our previous subject, when a runtime filter evaluates its script to return the n-th requested frame it does it in a block-wise manner, using the same mechanism as the "normal" script: the entire script is evaluated, a temporary filter-graph is created and a frame is requested from the temporary filter-graph; the result is returned to the caller. Thus, the runtime filter cannot know in advance what frame numbers its script will use, neither can it intercept the parsing of the script to adjust the value of current_frame. That would mean another parser, ie another Avisynth implementation; a very resource-costly thing. So, I would suggest to stick with the alternatives:
__________________
AVSLib, a free extension library for Avisynth. Current version: 1.1.0 (beta), 14/05/2007. [ Home page | Download page ] |
||
7th June 2008, 02:45 | #8 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
gzarkadas, I do already understand the script execution model (though I could easily be mistaken, and it's even more confusing than usual when you have nested run-time scripts).
Let's look again at my example, Code:
... # prelude ScriptClip(""" # start of outer FilterA() ScriptClip("FilterB()") # inner FilterC() """ # end of outer ... # postlude, rest of 'normal' script Because the statements of a run-time script are not evaluated until the frame-serving phase of the enclosing script, I say that the order of statement evaluation is Code:
prelude, outer ScriptClip, postlude, [FilterA, inner ScriptClip, FilterC, FilterB]* []* = repeated for each frame (I also conceded a more complex example might be able to demonstrate it. If you've got one, please post it here.) Where I do agree with you is that my idea of resetting current_frame on exit from GetFrame is pointless, since on the way out of the GetFrame chain, all the evaluations have already happened. Ah well, it was just an idea... I'm certainly not after anything that would require a new parser or changing the language (I'll leave that to the AviSynth 3.0 crew), just trying to understand exactly what the problem is and explore if there is a simple solution. If not, your suggested practical approaches are very sound. |
9th June 2008, 13:08 | #9 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
My 'solution' was designed to protect against an inner ScriptClip stamping on the value of current_frame set by an outer one before all statements that needed this value had been evaluated. But this cannot happen. The 'solution' has no effect because there was no 'problem' in the first place. The key point is that the evaluations of different run-time scripts never overlap in time, even if such scripts are nested. So I say current_frame can be allowed to be global with no ill effects. If you don't buy this argument, here's a more convincing one: Although current_frame is a local variable, it is 'local' at the same scope as the top-level script - a run-time script does not start a new scope. Thus there is only ever one instance of current_frame, which just gets re-used in a serial fashion for each run-time script. So making it truly global cannot break the way run-time scripts work; as far as I can see, the only effect would be to make it visible in functions, which is just what we need to solve my original problem with AverageLuma(). |
|
9th June 2008, 20:12 | #10 | Link |
Registered User
Join Date: Sep 2005
Location: 100011110010001000001 10000011111111000001
Posts: 221
|
I don't have the time to really check this in the depth that is required. However, a solution that does not require to recompile avisynth in order to use runtime functions inside user functions is to put the following line:
Code:
global current_frame = current_frame Code:
... ScriptClip("some script") FrameEvaluate("global current_frame = current_frame") ... # or if clips are assigned to variables ... c1 = c0.ScriptClip("some script") c2 = c1.FrameEvaluate("global current_frame = current_frame") # use c2 instead of c1 ... Code:
function G_ConditionalFilter(clip testclip, clip source1, clip source2, string function, string operator, string value, bool "show") { c = ConditionalFilter(testclip, source1, source2, function, operator, value, show) return c.FrameEvaluate("global current_frame = current_frame") } function G_ScriptClip(clip clip, string function, bool "show", bool "after_frame") { c = ScriptClip(clip, function, show, after_frame) return c.FrameEvaluate("global current_frame = current_frame") } function G_FrameEvaluate(clip clip, string function, bool "after_frame") { c = FrameEvaluate(clip, function, after_frame) return c.FrameEvaluate("global current_frame = current_frame") } function G_ConditionalReader(clip clip, string filename, string variablename, bool "show") { c = ConditionalReader(clip, filename, variablename, show) return c.FrameEvaluate("global current_frame = current_frame") }
__________________
AVSLib, a free extension library for Avisynth. Current version: 1.1.0 (beta), 14/05/2007. [ Home page | Download page ] |
9th June 2008, 20:15 | #11 | Link |
Registered User
Join Date: Sep 2005
Location: 100011110010001000001 10000011111111000001
Posts: 221
|
The solution works because when Avisynth requests a variable and it is not found at the active local scope, the global scope is then searched.
__________________
AVSLib, a free extension library for Avisynth. Current version: 1.1.0 (beta), 14/05/2007. [ Home page | Download page ] |
10th June 2008, 15:30 | #12 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Good thinking, gzarkadas - that does the trick very nicely indeed.
I may follow up the implementation issue on the development forum, but I think my original question has now been answered. To summarise the conclusions:
Last edited by Gavino; 10th June 2008 at 15:32. Reason: formatting |
|
|