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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 17th June 2014, 16:13   #1  |  Link
fvisagie
Registered User
 
Join Date: Aug 2008
Location: Isle of Man
Posts: 586
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)
This works correctly for monotonically increasing frame numbers. When the output is scrolled forwards and backwards the "Script runtime" starts displaying incorrect ClipFrame values. In some cases the ClipFrame values do not even change for a number of frames.

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
fvisagie is offline   Reply With Quote
Old 17th June 2014, 17:01   #2  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
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
You have to use the word "Global" to assign to a global.


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)
It still dont work , but now I can read it . Perchance the chosen one will happen by.

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.
StainlessS is offline   Reply With Quote
Old 17th June 2014, 23:17   #3  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
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.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 18th June 2014, 00:28   #4  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,340
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.
__________________
There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order. ~ Ed Howdershelt
foxyshadis is offline   Reply With Quote
Old 18th June 2014, 11:09   #5  |  Link
fvisagie
Registered User
 
Join Date: Aug 2008
Location: Isle of Man
Posts: 586
Quote:
Originally Posted by Gavino View Post
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.
I had assumed that TrackClip() was called even for re-requested frames because the frame numbers were still correctly subtitled, but I now suspect the previous frames had merely been cached and re-rendered along with previously rendered subtitles, right? Adding a Time()-stamp to subtitles seems to confirm that.

Quote:
Incidentally, the variable does not need to be global - run-time scripts run at the same scope as the outer script.
Thanks, I'd forgotten about that!

Quote:
Originally Posted by foxyshadis View Post
SetMemoryMax(0) will get you out of this jam
Thanks. It seems from 2.5.8 a small value should be used to (almost) disable the cache; 0 returns the current value.
fvisagie is offline   Reply With Quote
Old 18th June 2014, 11:52   #6  |  Link
Groucho2004
 
Groucho2004's Avatar
 
Join Date: Mar 2006
Posts: 3,743
Quote:
Originally Posted by fvisagie View Post
It seems from 2.5.8 a small value should be used to (almost) disable the cache; 0 returns the current value.
Correct. Also, 4 MB cache is the minimum.
Groucho2004 is offline   Reply With Quote
Old 18th June 2014, 16:11   #7  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
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 }
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 18th June 2014, 16:24   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
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.
StainlessS is offline   Reply With Quote
Old 18th June 2014, 17:36   #9  |  Link
Guest
Guest
 
Join Date: Jan 2002
Posts: 21,923
SetCacheHints(0,0) ?
Guest is offline   Reply With Quote
Old 18th June 2014, 18:22   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
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 ???
StainlessS is offline   Reply With Quote
Old 19th June 2014, 08:42   #11  |  Link
fvisagie
Registered User
 
Join Date: Aug 2008
Location: Isle of Man
Posts: 586
Thanks for the input and suggestions.

Quote:
Originally Posted by StainlessS View Post
a function to disable cache between two filters
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!
fvisagie is offline   Reply With Quote
Old 19th June 2014, 19:54   #12  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
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 ???
StainlessS is offline   Reply With Quote
Old 19th June 2014, 21:03   #13  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,021
Quote:
Originally Posted by StainlessS View Post
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.
it's an instance method on objects derived from IClip (see http://avisynth.nl/index.php/Cpluspl...#SetCacheHints), but I doubt it's useful for what I think you think it's useful for

Quote:
Originally Posted by fvisagie View Post
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!
It's not a script function, it's a C/C++ API function that plugin filters can use to tell their upstream filter which frames may be requested multiple times when GetFrame() is called. You can't use it from an Avisynth script.

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.
TheFluff is offline   Reply With Quote
Old 20th June 2014, 07:47   #14  |  Link
fvisagie
Registered User
 
Join Date: Aug 2008
Location: Isle of Man
Posts: 586
Thank you.
fvisagie is offline   Reply With Quote
Old 21st June 2014, 13:09   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
@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;
}
This does seem to work OK, but not very convenient
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.
StainlessS is offline   Reply With Quote
Old 21st June 2014, 14:20   #16  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
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); }
};
It does output the "SetCacheHints requested our 'this' pointer" to debugview, but does not suppress caching,
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.
StainlessS is offline   Reply With Quote
Old 21st June 2014, 15:08   #17  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,021
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
So you're basically in the exact same place as before, you've just added what amounts to a no-op to the filter chain.

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?
TheFluff is offline   Reply With Quote
Old 21st June 2014, 15:28   #18  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,681
Quote:
Originally Posted by TheFluff View Post
Have I mentioned lately that I think all these runtime hacks are a really bad idea?
Yes, I do seem to recall you saying something like that, however,
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 ???
StainlessS is offline   Reply With Quote
Old 25th June 2014, 16:08   #19  |  Link
fvisagie
Registered User
 
Join Date: Aug 2008
Location: Isle of Man
Posts: 586
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}")
caching is only disabled from that point onward. Useful-looking, but in this case I'm trying to globally disable caching.

With
Code:
function DisableCache() {
    function Cache(clip c) {return c}
}
condition ? DisableCache() : NOP()
caching is disabled even when DisableCache() isn't invoked!

Code:
function InternalCache(clip c) {return c}
seems to have no discernable effect.

Code:
SetMemoryMax(4)
doesn't sufficiently disable caching in some cases. SetMemoryMax() accepts values down to 1 but without noticeable improvement.

Any ideas?
fvisagie is offline   Reply With Quote
Old 25th June 2014, 16:38   #20  |  Link
Guest
Guest
 
Join Date: Jan 2002
Posts: 21,923
Did you read what TheFluff wrote above?
Guest is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 04:54.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.