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. |
17th June 2014, 16:13 | #1 | Link |
Registered User
Join Date: Aug 2008
Location: Isle of Man
Posts: 588
|
Passing values between runtime scripts
Hi All,
I'm having trouble reliably updating information between separate runtime scripts. The runtime scripts are used to track and display input clip frame number at frame serving time. As a rule the top ScriptClip only records the input clip frame number for the bottom one to display, the idea being that a Subtitle at the end of the script should better survive geometric transformation. Code:
function TrackClip(clip c, bool "debug") { ScriptClip(c, """ClipFrame = current_frame debug = """" + String(debug) + """" (debug == "true") ? Subtitle("Clip runtime:" + "\n" + \ "ClipFrame:" + String(ClipFrame), align=7, lsp=1) \ : last """, after_frame=false) } global ClipFrame = 0 BlankClip(fps=25.0, color=$000000) clip1 = TrackClip(debug=true) BlankClip(fps=25.0, color=$FFFFFF) clip2 = TrackClip(debug=true) clip1.Trim(199, 201) ++ clip2.Trim(49, 51) ScriptClip("""Subtitle("Script runtime:" + "\n" + \ "ClipFrame: " + String(ClipFrame) + "\n" + \ "script current_frame: " + String(current_frame), align=9, lsp=1) """, after_frame=true) However, in all cases the "Script runtime" is still invoked every frame as shown by it correctly updating the "script current_frame" value, and the "Clip runtime" is also still invoked every frame as shown by correct updates to its ClipFrame display when enabled. It's just that somehow the "Script runtime" does not see these ClipFrame updates! I've played with after_frame settings and the ones above seem to work best. Using FrameEvaluate() instead of ScriptClip() for the "Clip runtime" makes no difference. What else can I try to get this to work for shuttled output? If for some fundamental reason this won't work, what other method can I use to track input clip frame numbers and display them at render time for shuttled output? Many thanks, Francois |
17th June 2014, 17:01 | #2 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
I have not played with this, but this stood out a little
Code:
function TrackClip(clip c, bool "debug") { ScriptClip(c, """Global ClipFrame = current_frame debug = """" + String(debug) + """" (debug == "true") ? Subtitle("Clip runtime:" + "\n" + \ "ClipFrame:" + String(ClipFrame), align=7, lsp=1) \ : last """, after_frame=false) } global ClipFrame = 0 EDIT: I found it a little difficult to read, so changed as here Code:
Global ClipFrame = 0 Function TrackClip(clip c, bool "debug") { debug=Default(debug,false) ES = """ Global ClipFrame = current_frame Subtitle("Clip runtime:\nClipFrame: " + String(ClipFrame) + "\nscript current_frame: " + String(current_frame), align=7, lsp=1) Global ClipFrame = current_frame # This dont make any difference Return Last """ (debug) ? c.ScriptClip(ES, after_frame=false) : c } BlankClip(fps=25.0, color=$000000).ShowFrameNumber # Added ShowFrameNumber clip1 = TrackClip(debug=true) BlankClip(fps=25.0, color=$FFFFFF).ShowFrameNumber clip2 = TrackClip(debug=true) clip1.Trim(199, 201) ++ clip2.Trim(49, 51) SCS=""" Subtitle("Script runtime:\nClipFrame: " + String(ClipFrame) + "\nscript current_frame: " + String(current_frame), align=4, lsp=1) """ ScriptClip(SCS, after_frame=true) EDIT: ShowFrameNumber works OK, but it dont explain the Scriptclip Global stuff. Perhaps this will suffice:- Code:
DEBUG=True BlankClip(fps=25.0, color=$000000) clip1 = (DEBUG) ? ShowFrameNumber : Last BlankClip(fps=25.0, color=$FFFFFF) clip2 = (DEBUG) ? ShowFrameNumber : Last clip1.Trim(199, 201) ++ clip2.Trim(49, 51)
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 17th June 2014 at 18:52. |
17th June 2014, 23:17 | #3 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
What you are seeing is a side effect of the Avisynth cache.
The variable ClipFrame is changed only when the run-time script inside function TrackClip() is executed. When a given frame is requested for a second (or later) time, it is likely to be found first in a downstream cache, and then the run-time script will not be executed. Incidentally, the variable does not need to be global - run-time scripts run at the same scope as the outer script. |
18th June 2014, 00:28 | #4 | Link |
ангел смерти
Join Date: Nov 2004
Location: Lost
Posts: 9,558
|
SetMemoryMax(0) will get you out of this jam, but it will seriously drop the speed of every temporal function. You can raise it up to just below where it will stop working as you need for each script/video, but it might be a better idea to use a can't-fail method like tacking a subtitled box to the bottom of the frame; that would generally survive filtering without impacting it much.
|
18th June 2014, 11:09 | #5 | Link | ||
Registered User
Join Date: Aug 2008
Location: Isle of Man
Posts: 588
|
Quote:
Quote:
Thanks. It seems from 2.5.8 a small value should be used to (almost) disable the cache; 0 returns the current value. |
||
18th June 2014, 16:11 | #7 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Because there is a minimum value, you cannot disable the cache completely using SetMemoryMax().
However, in v2.60, you can effectively disable it by redefining the Cache() function (in your script) as follows: Code:
function Cache(clip c) { return c } |
18th June 2014, 16:24 | #8 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
I'm not sure, but I think I've seen a function to disable cache between two filters,
Don't remember which plugin it lives in. Anybody know? PS,great tip G. Edit, may have been a kassandro plug. Cache, & internalcache seem to be the same & undocumented built-in func.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 18th June 2014 at 16:49. |
18th June 2014, 18:22 | #10 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Thank you n2
Much appreciated.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
19th June 2014, 08:42 | #11 | Link |
Registered User
Join Date: Aug 2008
Location: Isle of Man
Posts: 588
|
Thanks for the input and suggestions.
Why do you say "between two filters"? Are you perhaps implying that in cases like this one could selectively disable and re-enable caching at different points in the script? How do you suggest using SetCacheHints() in a script like this? What values can the parameters of SetCacheHints() take and what do they mean? How does one re-enable caching? References on this forum are very few, along with a request for documentation! |
19th June 2014, 19:54 | #12 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
I was thinking of disabling cache during plugin testing, and only at specific points in filter chain.
I have not as yet found which plugin that function lives in.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
19th June 2014, 21:03 | #13 | Link | ||
Excessively jovial fellow
Join Date: Jun 2004
Location: rude
Posts: 1,100
|
Quote:
Quote:
Basically, what it does is tell Avisynth that when this filter requests frames from an upstream filter (the previous filter in the chain), it should either cache nothing (every frame requested from this filter results in one call to GetFrame() on the upstream filter per frame needed to produce an output frame), cache a fixed range of frames around the latest requested frame (useful for a temporal filter where, say, requesting frame n would require getting get n-1 and n+1; thus, if we cache those two frames, when you request one of them at least one of the new frames needed will be cached) or just use as much available memory as it finds suitable on a least-recently-used cache. See also http://forum.doom9.org/showthread.ph...50#post1595750 Last edited by TheFluff; 19th June 2014 at 21:21. |
||
21st June 2014, 13:09 | #15 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
@TheFluff, thank you, but I was perhaps mistaken in that I thought I remembered a script function for removing cache from between
two filters (or not inserting one, ie add your own dummy filter that pretends to be Cache so that an additional following cache would not be added). EDIT: I assumed that Neuron2 was giving me the name of a script function, I am aware of SetCacheHints in Avisynth.h. From v2.6a5 source Code:
/*********** C R E A T E ************/ AVSValue __cdecl Cache::Create_Cache(AVSValue args, void*, IScriptEnvironment* env) { PClip p=0; if (args.IsClip()) p = args.AsClip(); else p = args[0].AsClip(); if (p) { int q = 0; if (p->GetVersion() >= 5) // AVISYNTH_INTERFACE_VERSION which supports this q = p->SetCacheHints(GetMyThis, 0); // Check if "p" is a cache instance // Do not cache another cache! if (q != (int)(void *)p) return new Cache(p, env); } return p; } Code:
Global ClipFrame = 0 Function Cache(clip c){return c} # Disable built-in Cache Function TrackClip(clip c, bool "debug") { debug=Default(debug,false) ES = """ Global ClipFrame = current_frame Subtitle("Clip runtime:\nClipFrame: " + String(ClipFrame) + "\nscript current_frame: " + String(current_frame), align=7, lsp=1) Return Last """ (debug) ? c.ScriptClip(ES, after_frame=false) : c } # Cache output of ShowFrameNumber using built-in alternative name for Cache() clip1 = BlankClip(fps=25.0, color=$000000).ShowFrameNumber.InternalCache().TrackClip(debug=true) clip2 = BlankClip(fps=25.0, color=$FFFFFF).ShowFrameNumber.InternalCache().TrackClip(debug=true) clip1.Trim(199, 201) ++ clip2.Trim(49, 51) SCS=""" Subtitle("Script runtime:\nClipFrame: " + String(ClipFrame) + "\nscript current_frame: " + String(current_frame), align=4, lsp=1) """ ScriptClip(SCS, after_frame=true) # No Cache between TrackClip calls and ScriptClip() InternalCache() # Can Cache after Scriptclip
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 21st June 2014 at 14:20. |
21st June 2014, 14:20 | #16 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Tried this but it dont work (after liberally scattering lots of NoCache()'s about.)
intended for v2.6 Code:
class NoCache : public GenericVideoFilter { private: enum {GetMyThis = 0x8686 }; // Stolen from Avisynth source public: NoCache(PClip _child,IScriptEnvironment* env) : GenericVideoFilter(_child) {} ~NoCache(){} // void __stdcall SetCacheHints(int cachehints,int frame_range); SHOULD return void int __stdcall SetCacheHints(int cachehints,int frame_range) { // Cheat and return int (as v2.5) if(cachehints==GetMyThis) { dprintf("SetCacheHints requested our 'this' pointer"); return (int)(void *)this; // return (int)(void *)child; // Dont work either } return 0; } PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); } }; so we seem to be returning the wrong PClip. EDIT: Returning 'child' rather than 'this' dont work either.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 21st June 2014 at 15:13. |
21st June 2014, 15:08 | #17 | Link |
Excessively jovial fellow
Join Date: Jun 2004
Location: rude
Posts: 1,100
|
I think you've missed a rather significant point: SetCacheHints() only works in one direction, so even if your pretend-to-be-a-cache filter worked (and I don't think it does; I'd suggest using an interactive debugger instead of sprinkling printf's around) you'd still get the following scenario:
Code:
SomeFilter --(getframe with cache)--> NoCache --(getframe with no cache)--> SourceFilter Basically, you can't tell Avisynth to not cache your output. What SetCacheHints(0, 0) does is tell Avisynth to not cache your input, which is not really what you want. To do what you actually want you'd have to disable caching in the downstream direction as well, and there's no way to do that. Have I mentioned lately that I think all these runtime hacks are a really bad idea? |
21st June 2014, 15:28 | #18 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Quote:
if the situation as it stands is lacking then some improvisation may be called for. Ideally it would not be necessary. and thanks for your clarification.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
|
25th June 2014, 16:08 | #19 | Link |
Registered User
Join Date: Aug 2008
Location: Isle of Man
Posts: 588
|
I'm having some trouble dynamically disabling the cache (and wrapping that in a function for that matter).
When I go Code:
condition ? Eval("function Cache(clip c) {return c}") : NOP() # or simply Eval("function Cache(clip c) {return c}") With Code:
function DisableCache() { function Cache(clip c) {return c} } condition ? DisableCache() : NOP() Code:
function InternalCache(clip c) {return c} Code:
SetMemoryMax(4) Any ideas? |
Thread Tools | Search this Thread |
Display Modes | |
|
|