GRunT

From Avisynth wiki
(Difference between revisions)
Jump to: navigation, search
m (add links, use Template:FuncDef, Template:BoxWidthIndent more TODO)
(more content imported from docfile)
Line 1: Line 1:
 
{{FilterCat|External_filters|Plugins|Support_filters}}
 
{{FilterCat|External_filters|Plugins|Support_filters}}
 
{{Filter3
 
{{Filter3
| Gavino
+
| {{Author/Gavino}}
 
| v1.0.1
 
| v1.0.1
 
| 3=[http://forum.doom9.org/attachment.php?s=e3dfd39b17aff991b34523778ca798f5&attachmentid=8852&d=1222533692 GRunT101.zip]
 
| 3=[http://forum.doom9.org/attachment.php?s=e3dfd39b17aff991b34523778ca798f5&attachmentid=8852&d=1222533692 GRunT101.zip]
| 4=Support filters
+
| 4=[[:Category:Support_filters|Support filters]]
 
| 5=[http://www.gnu.org/licenses/gpl-2.0.txt GPLv2]
 
| 5=[http://www.gnu.org/licenses/gpl-2.0.txt GPLv2]
 
| 6=[http://forum.doom9.org/showthread.php?t=139337 Doom9 Thread]}}
 
| 6=[http://forum.doom9.org/showthread.php?t=139337 Doom9 Thread]}}
 
<br>
 
<br>
 
== Description ==
 
== Description ==
AviSynth's [[Runtime_environment|run-time environment]] is very powerful, supporting complex video processing that would be difficult or impossible to perform in a normal script. But it's not easy to use - the behaviour of run-time scripts (especially in combination) can be hard to understand and there are usability problems concerning [[The_script_execution_model/Scope_and_lifetime_of_variables#Runtime_scripts|scope and lifetime of variables]].
+
[[Main_Page|AviSynth]]'s [[Runtime_environment|run-time environment]] is very powerful, supporting complex video processing that would be difficult or impossible to perform in a normal script. But it's not easy to use - the behaviour of run-time scripts (especially in combination) can be [http://forum.doom9.org/showthread.php?p=338712#post338712 hard to understand], and there are usability problems concerning [[The_script_execution_model/Scope_and_lifetime_of_variables#Runtime_scripts|scope and lifetime of variables]].
  
[[GRunT]] (Gavino's Run-Time ) is a plugin which addresses these and other problems, making the run-time system much easier to use.
+
'''[[GRunT]]''' (Gavino's Run-Time ) is a plugin which addresses these and other problems, making the run-time system much easier to use.
 
<br>
 
<br>
 
<br>
 
<br>
Line 19: Line 19:
 
* Run-time functions can be called from a user function
 
* Run-time functions can be called from a user function
 
* Run-time functions can be applied to any frame (relative to the current one)
 
* Run-time functions can be applied to any frame (relative to the current one)
* Additional variant of [[ConditionalFilter]] with single boolean expression
+
* Additional variant of [[#ConditionalFilter]] with a single boolean expression
 
* Fixes a fairly serious [http://forum.doom9.org/showthread.php?t=138755 bug] in the run-time system
 
* Fixes a fairly serious [http://forum.doom9.org/showthread.php?t=138755 bug] in the run-time system
 
* Lightweight plugin extending the standard run-time environment with minimal time and memory overhead
 
* Lightweight plugin extending the standard run-time environment with minimal time and memory overhead
 
* 100% backwards compatible with existing scripts
 
* 100% backwards compatible with existing scripts
  
'''GRunT''' should be useful to anyone who uses the run-time filters, from those who make occasional use of [[ScriptClip]] to those who write complex functions based on run-time features (such as Restore24 or MRestore).
+
'''GRunT''' should be useful to anyone who uses run-time filters, from those who make occasional use of [[ScriptClip]] to those who write complex functions based on run-time features (such as [[Restore24]] or [[Mrestore]]).
 
<br>
 
<br>
 
<br>
 
<br>
== Syntax and Parameters ==
+
== A variables scope and lifetime example ==
  
 +
A short example (please compare to the [[The_script_execution_model/Scope_and_lifetime_of_variables#A_variables_scope_and_lifetime_example|original]]) shows how this greatly simplifies passing function parameters into a run-time script.
 +
<div {{BoxWidthIndent|60|2}}>
 +
function bracket_luma(clip c, float th1, float th2) {
 +
    Assert(0 <= th1 && th1 < th2 && th2 <= 255, "Invalid thresholds!")
 +
    ScriptClip(c, """
 +
        avl = AverageLuma()
 +
        avl <= th1 ? last.BlankClip() : avl >= th2 ? last.BlankClip(color=color_white) : last
 +
    """, args="th1,th2", local=true)
 +
}
 +
</div>
 +
This is much easier than the standard approach of dynamically building the runtime script using string concatenation, or passing the values via global variables.
  
===Run-Time filters:===
+
Because the run-time script is evaluated in its own scope, there is now no problem in calling ''bracket_luma'' more than once in the same script (previously the variables ''th1'' and ''th2'' of different instances could interfere with each other).  
The plugin provides extended versions of the following run-time filters:
+
* [[ScriptClip#ScriptClip|ScriptClip]]
+
:{{FuncDef|ScriptClip(clip, string, bool "showx", bool "after_frame", string "args", bool "local")}}
+
:{{FuncDef|GScriptClip(clip, string, bool "show", bool "after_frame", string "args", bool "local")}}
+
* [[FrameEvaluate#FrameEvaluate|FrameEvaluate]]
+
:{{FuncDef|FrameEvaluate(clip, string, bool "showx", bool "after_frame", string "args", bool "local")}}
+
:{{FuncDef|GFrameEvaluate(clip, string, bool "show", bool "after_frame", string "args", bool "local")}}
+
* [[ConditionalFilter]]
+
:{{FuncDef|ConditionalFilter(clip, clip, clip, string, bool "showx", string "args", bool "local")}}
+
:{{FuncDef|ConditionalFilter(clip, clip, clip, string, string, string, bool "showx", string "args", bool "local")}}
+
:{{Template:FuncDef|GConditionalFilter(clip, clip, clip, string, bool "show", string "args", bool "local")}}
+
:{{FuncDef|GConditionalFilter(clip, clip, clip, string, string, string, bool "show", string "args", bool "local")}}
+
* [[WriteFile]]
+
:{{FuncDef|WriteFile(clip, string "filenamex", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")}}
+
:{{FuncDef|GWriteFile(clip, string "filename", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")}}
+
* [[WriteFileIf]]
+
:{{FuncDef|WriteFileIf(clip, string "filenamex", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")}}
+
:{{FuncDef|GWriteFileIf(clip, string "filename", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")}}
+
  
The alternative ({{FuncDef|G*}}) names <!-- {{FuncDef|GScriptClip, GFrameEvaluate, GConditionalFilter, GWriteFile}} and {{FuncDef|GWriteFileIf}} -->may also be used. However, if running on AviSynth version 2.57 or earlier, then the alternative names '''must''' be used.<br>
+
 
(This restriction is necessary for technical reasons - sorry about that.)
+
== Run-time Filters ==
 +
 
 +
'''GRunT''' provides extended versions of the following run-time filters:
 +
===== ''[[ScriptClip#ScriptClip|ScriptClip]]'' =====
 +
<div {{BoxWidthIndent|70|2}} >
 +
{{Func2Def
 +
|ScriptClip(clip ''clip'', string ''filter'' [, bool ''showx'', bool ''after_frame'', string ''args'', bool ''local''])
 +
|GScriptClip(clip ''clip'', string ''filter'' [, bool ''show'', bool ''after_frame'', string ''args'', bool ''local''])}}
 +
</div>
 +
 
 +
===== ''[[FrameEvaluate#FrameEvaluate|FrameEvaluate]]'' =====
 +
<div {{BoxWidthIndent|70|2}} >
 +
{{Func2Def
 +
|FrameEvaluate(clip ''clip'', string ''filter'', [, bool ''showx'', bool ''after_frame'', string ''args'', bool ''local''])
 +
|GFrameEvaluate(clip ''clip'', string ''filter'' [, bool ''show'', bool ''after_frame'', string ''args'', bool ''local''])}}
 +
</div>
 +
 
 +
===== ''[[ConditionalFilter]]'' =====
 +
<div {{BoxWidthIndent|70|2}} >
 +
{{Func2Def
 +
|ConditionalFilter(clip ''testclip'', clip ''source1'', clip ''source2'', string ''expression1'', string ''operator'', string ''expression2'' 
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''showx'', string ''args'', bool ''local''])
 +
|GConditionalFilter(clip ''testclip'', clip ''source1'', clip ''source2'', string ''expression1'', string ''operator'', string ''expression2'' 
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''show'', string ''args'', bool ''local''])}}
 +
<br>
 +
 
 +
{{Func2Def
 +
|ConditionalFilter(clip ''testclip'', clip ''source1'', clip ''source2'', string ''expression''
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''showx'', string ''args'', bool ''local''])
 +
|GConditionalFilter(clip ''testclip'', clip ''source1'', clip ''source2'', string ''expression''
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''show'', string ''args'', bool ''local''])}}
 +
</div>
 +
 
 +
===== ''[[WriteFile]]'' =====
 +
<div {{BoxWidthIndent|70|2}} >
 +
{{Func2Def
 +
|WriteFile(clip ''clip'', string ''filename'', string ''expression1'' [, string ''expression2'' [, ...]]
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''append'', bool ''flush'', string ''args'', bool ''local''])
 +
|GWriteFile(clip ''clip'', string ''filename'', string ''expression1'' [, string ''expression2'' [, ...]]
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''append'', bool ''flush'', string ''args'', bool ''local''])}}
 +
</div>
 +
 
 +
===== ''[[WriteFileIf]]'' =====
 +
<div {{BoxWidthIndent|70|2}} >
 +
{{Func2Def
 +
|WriteFileIf(clip ''clip'', string ''filename'', string ''expression1'' [, string ''expression2'' [, ...]]
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''append'', bool ''flush'', string ''args'', bool ''local''])
 +
|GWriteFileIf(clip ''clip'', string ''filename'', string ''expression1'' [, string ''expression2'' [, ...]]
 +
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''append'', bool ''flush'', string ''args'', bool ''local''])}}
 +
</div>
 +
The alternative ({{FuncDef|G*}}) names may be used if you wish, but this is optional in AviSynth version 2.58 or later.
  
  
Line 57: Line 100:
  
 
:*''string'' {{FuncDef|args}}: the variables whose values are to be imported into the run-time script, written as a list of names separated by commas. The given variable names are evaluated in the current (compile-time) context, so can include function parameters or local variables. Each value becomes the initial value of the corresponding variable at each invocation of the run-time script.
 
:*''string'' {{FuncDef|args}}: the variables whose values are to be imported into the run-time script, written as a list of names separated by commas. The given variable names are evaluated in the current (compile-time) context, so can include function parameters or local variables. Each value becomes the initial value of the corresponding variable at each invocation of the run-time script.
 +
{{BlueBox}}
 +
*Elements of the <span style="color: purple; font-weight: bold">args</span> string can also take the form <tt>''name=expression''</tt>; the expression is evaluated in the current context and sets the value of the named variable.<br>
 +
:Example: <br>
 +
<pre style="width:20em;margin:0 0 0 3em;padding:0;border:none;">
 +
args="x, y=n+1, c=c.Trim(2, 0)"
 +
</pre>
 +
:will set values for the variables ''x'', ''y'' and ''c''. Here ''y'' need not even exist in the current environment (although ''x'', ''n'' and ''c'' must exist).
 +
 +
*The simple form (without the expression) is just a shorthand for the more general form, with the variable name itself being used as the expression. So, for example,
 +
<pre style="width:20em;margin:0 0 0 3em;padding:0;border:none;">
 +
args="x, y, z"
 +
</pre>
 +
:is equivalent to
 +
<pre style="width:20em;margin:0 0 0 3em;padding:0;border:none;">
 +
args="x=x, y=y, z=z"
 +
</pre>
 +
:passing the values of the compile-time variables ''x'', ''y'' and ''z'' (from outside the run-time script) into the variables of the same name inside the script.
 +
 +
*Spaces may be freely used (or not) inside the <span style="color: purple; font-weight: bold">args</span> string, just as in Avisynth function calls.
 +
{{End_BlueBox}}
 +
 
:*''bool'' {{FuncDef|local}}: if true, the filter will evaluate its run-time script in a new variable scope, avoiding unintended sharing of variables between run-time scripts. Default is true if args is also specified, otherwise false (to preserve backwards compatibility).
 
:*''bool'' {{FuncDef|local}}: if true, the filter will evaluate its run-time script in a new variable scope, avoiding unintended sharing of variables between run-time scripts. Default is true if args is also specified, otherwise false (to preserve backwards compatibility).
  
 +
[[TODO]] - document {{FuncDef|show}}, {{FuncDef|showx}}
  
A short example (based on the original) shows how this greatly simplifies passing function parameters into a run-time script.
+
 
<div {{BoxWidthIndent|60|2}}>
+
== Run-time Functions ==
  function bracket_luma(clip c, float th1, float th2) {
+
The plugin also provides the following extensions to the run-time functions (such as AverageLuma):
    Assert(0 <= th1 && th1 < th2 && th2 <= 255, "Invalid thresholds!")
+
 
    ScriptClip(c, """
+
* These functions can now be called inside a user function, when (and only when) the user function is called from a run-time script.  
      avl = AverageLuma()
+
* Each function has a new optional ''int'' argument, which can be used to get the value from another frame, relative to the current one.For example, <tt>AverageLuma(-1)</tt> returns the value for the previous frame.
      avl <= th1 ? last.BlankClip() : avl >= th2 ? last.BlankClip(color=color_white) : last
+
 
    """, args="th1,th2", local=true)
+
Note that to support the first feature, ''current_frame'' is now a ''global'' variable (see [http://forum.doom9.org/showthread.php?t=138392 discussion]). However, the second feature means that it is no longer necessary to change ''current_frame'' to access other frames. In fact, for most purposes, you can forget that ''current_frame'' exists as an explicit variable.
 +
 
 +
Here is an example of a weighted second order luma interpolation function:
 +
<div {{BoxWidthIndent|40|1}}>
 +
  function InterpLuma2(clip c) {
 +
    lm_k = AverageLuma(c)
 +
    lm_km1 = AverageLuma(c, -1)
 +
    lm_kp1 = AverageLuma(c, 1)
 +
    dvg = (lm_km1 - 2 * lm_k + lm_kp1) / 2
 +
    return lm_k + Sign(dvg) * Sqrt(Abs(dvg))
 
  }
 
  }
 
</div>
 
</div>
This is much easier than the standard approach of dynamically building the runtime script using string concatenation, or passing the values via global variables.
+
This function can be called from any run-time script. Previously, something like this this had to be done by assigning to ''current_frame'' (or using additional filters, eg Trim(1,0)), and the code had to be written directly in the run-time script rather than in a function.  
  
And because the run-time script is evaluated in its own scope, there is now no problem in calling bracket_luma more than once in the same script (previously the variables th1 and th2 of different instances could interfere with each other).  
+
In effect, we are now able to write run-time functions of our own, derived from the standard ones. Here is another example:
 +
<div {{BoxWidthIndent|40|1}}>
 +
function AverageRed(clip c) {
 +
    return RGBDifference(ShowRed(c), BlankClip(c))
 +
}
 +
</div>
 +
Note too that, while useful in its own right, the ability to call run-time functions in a user function gives you more than just that. For the first time, it allows an ''entire'' run-time script to be put inside a function body, called for example like this:
 +
<div {{BoxWidthIndent|20|1}}>
 +
ScriptClip("MyFunc()")
 +
</div>
 +
As the function body will be evaluated in a separate scope, this is another way of eliminating the problem of unintended sharing of variables between run-time scripts. However, you may prefer to write the run-time script 'in-line' and invoke the run-time filter with ''local=true''.  
  
  
Elements of the <code>args string</code> can also take the form <tt>'name=expression'</tt> - the expression is evaluated in the current context and is used to set the value of the named variable in the run-time script.<br>
+
Here is the complete list of [[Internal_functions/Runtime_functions#Runtime_functions|run-time functions]], with their extended interface.
Example: <code>args="x, y=n+1, c=c.Trim(2, 0)"</code> will provide values for the variables x, y and c.<br>
+
===== [[Internal_functions/Runtime_functions#Average|Average]] =====
Here y need not even exist in the current environment (although x, n and c must).
+
:<code>AverageLuma (clip [, int offset])</code>
 +
:<code>AverageChromaU (clip [, int offset])</code>
 +
:<code>AverageChromaV (clip [, int offset])</code>
 +
 
 +
===== [[Internal_functions/Runtime_functions#Difference|Difference]] =====
 +
:<code>RGBDifference (clip1, clip2 [, int offset])</code>
 +
:<code>LumaDifference (clip1, clip2 [, int offset])</code>
 +
:<code>ChromaUDifference (clip1, clip2 [, int offset])</code>
 +
:<code>ChromaVDifference (clip1, clip2 [, int offset])</code>
 +
 
 +
===== [[Internal_functions/Runtime_functions#Difference_from_previous|Difference from previous]] =====
 +
:<code>RGBDifferenceFromPrevious (clip [, int offset])</code>
 +
:<code>YDifferenceFromPrevious (clip [, int offset])</code>
 +
:<code>UDifferenceFromPrevious (clip [, int offset])</code>
 +
:<code>VDifferenceFromPrevious (clip [, int offset])</code>
 +
 
 +
===== [[Internal_functions/Runtime_functions#Difference_to_next|Difference to next]] =====
 +
:<code>RGBDifferenceToNext (clip [, int offset])</code>
 +
:<code>YDifferenceToNext (clip [, int offset])</code>
 +
:<code>UDifferenceToNext (clip [, int offset])</code>
 +
:<code>VDifferenceToNext (clip [, int offset])</code>
 +
 
 +
===== [[Internal_functions/Runtime_functions#Color_plane_median.2C_min.2C_max.2C_range|Color plane median, min, max, range]] =====
 +
:<code>YPlaneMax (clip, float threshold [, int offset])</code>
 +
:<code>UPlaneMax (clip, float threshold [, int offset])</code>
 +
:<code>PlaneMax (clip, float threshold [, int offset])</code>
 +
:<code>YPlaneMin (clip, float threshold [, int offset])</code>
 +
:<code>UPlaneMin (clip, float threshold [, int offset])</code>
 +
:<code>VPlaneMin (clip, float threshold [, int offset])</code>
 +
:<code>YPlaneMedian (clip [, int offset])</code>
 +
:<code>UPlaneMedian (clip [, int offset])</code>
 +
:<code>VPlaneMedian (clip [, int offset])</code>
 +
:<code>YPlaneMinMaxDifference (clip, float threshold [, int offset])</code>
 +
:<code>UPlaneMinMaxDifference (clip, float threshold [, int offset])</code>
 +
:<code>VPlaneMinMaxDifference (clip, float threshold [, int offset])</code>
 +
 
 +
The optional {{FuncDef|offset}} parameter specifies the offset (which may be negative) from the current frame; default is zero.
 +
 
 +
 
 +
== ConditionalFilter ==
 +
For added convenience, there is a new variant of [[ConditionalFilter]] which takes a single boolean expression instead of three separate parameters as at present. This is useful when the condition to be tested is a compound one or is already available in boolean form (like <tt>IsCombed()</tt>).
 +
 
 +
For example,
 +
ConditionalFilter(c, c1, c2, "AverageLuma(c1) > AverageLuma() && AverageLuma(c1) > AverageLuma(c2)")
 +
where previously you would have to say
 +
ConditionalFilter(c, c1, c2, "AverageLuma(c1) > AverageLuma() && AverageLuma(c1) > AverageLuma(c2)", "=",
 +
 
 +
Note that this form of ConditionalFilter also makes it easier use the relational operators <tt><=</tt>, <tt>>=</tt> and <tt>!=</tt>, which are not supported as the ''operator'' in the standard [[ConditionalFilter]].
 +
 
 +
<!-- NOT SURE IF CURRENT INFO
 +
== Bug fix ==
 +
The plugin fixes a fairly serious [http://forum.doom9.org/showthread.php?t=138755 bug] I discovered in the run-time system. This fix is needed if you are running a version of Avisynth prior to build 080620 of 2.58. (GRunT actually originated as a means to demonstrate this bug-fix, but I have now extended it to do a lot more.)  
 +
 
 +
Since things like [[ScriptClip]] are often hidden deep inside huge functions like [[Restore24]], you may be affected by this bug without even realising it.  
 +
-->
 +
 
 +
== Configuration ==
 +
For the extended run-time filters, for compatibility reasons the default for {{FuncDef|local}} is ''false'' unless {{FuncDef|args}} is also specified. However, it is recommended to always use ''local=true'' unless you really need to communicate values of variables from one run-time script to another (note that you can always use global variables for this).
 +
 
 +
To this end, the plugin provides '''GRTConfig''':
 +
:{{FuncDef|GRTConfig(bool ''local'')}}
 +
 
 +
<tt>GRTConfig(local=true)</tt> sets ''local=true'' by default for all subsequent filters.
 +
 
  
<br>
 
== Examples ==
 
TO DO
 
<br>
 
<br>
 
 
== Changelog ==
 
== Changelog ==
<pre>v1.0.1 (Gavino, 27th September 2008):
+
*v1.0.1 (Gavino, 27th September 2008):
- fix for Avisynth 2.5.7 (have to use alternative names for filters, eg GScriptClip)
+
:- fix for Avisynth 2.5.7 (have to use alternative names for filters, eg GScriptClip)
 +
 
 +
*v1.0.0 (Gavino, 9th July 2008):
 +
:- add 'args' and 'local' to filters
 +
:- run-time functions with offset from current_frame
 +
:- new variant of ConditionalFilter (single boolean expr)
 +
 
 +
*v0.1 (Gavino, 18th June 2008):
 +
:- fix Avisynth bug in setting of current_frame
 +
:- make current_frame global (allows run-time functions to be cslled inside user functions)
  
v1.0.0 (Gavino, 9th July 2008):
 
- add 'args' and 'local' to filters
 
- run-time functions with offset from current_frame
 
- new variant of ConditionalFilter (single boolean expr)
 
  
v0.1 (Gavino, 18th June 2008):
 
- fix Avisynth bug in setting of current_frame
 
- make current_frame global (allows run-time functions to be cslled inside user functions)</pre>
 
<br>
 
 
== Archived Downloads ==
 
== Archived Downloads ==
 
{| class="wikitable" border="1"; width="600px"
 
{| class="wikitable" border="1"; width="600px"
Line 110: Line 253:
 
|}
 
|}
 
<br>
 
<br>
==External Links ==
+
''Document v1.0.1 ({{Author/Gavino}}, 27th September 2008)''
<br>
+
 
<br>
+
 
-----------------------------------------------
 
-----------------------------------------------
 
'''Back to [[External_filters#Support_filters|External Filters]] &larr;'''
 
'''Back to [[External_filters#Support_filters|External Filters]] &larr;'''

Revision as of 02:05, 5 January 2016

Abstract
Author Gavino
Version v1.0.1
Download GRunT101.zip
Category Support filters
License GPLv2
Discussion Doom9 Thread


Contents

Description

AviSynth's run-time environment is very powerful, supporting complex video processing that would be difficult or impossible to perform in a normal script. But it's not easy to use - the behaviour of run-time scripts (especially in combination) can be hard to understand, and there are usability problems concerning scope and lifetime of variables.

GRunT (Gavino's Run-Time ) is a plugin which addresses these and other problems, making the run-time system much easier to use.

Features

  • Simple, natural and robust way to pass variables into a run-time script from 'outside'
  • A run-time script can be evaluated in its own independent scope
  • Run-time functions can be called from a user function
  • Run-time functions can be applied to any frame (relative to the current one)
  • Additional variant of #ConditionalFilter with a single boolean expression
  • Fixes a fairly serious bug in the run-time system
  • Lightweight plugin extending the standard run-time environment with minimal time and memory overhead
  • 100% backwards compatible with existing scripts

GRunT should be useful to anyone who uses run-time filters, from those who make occasional use of ScriptClip to those who write complex functions based on run-time features (such as Restore24 or Mrestore).

A variables scope and lifetime example

A short example (please compare to the original) shows how this greatly simplifies passing function parameters into a run-time script.

function bracket_luma(clip c, float th1, float th2) {
    Assert(0 <= th1 && th1 < th2 && th2 <= 255, "Invalid thresholds!")
    ScriptClip(c, """
       avl = AverageLuma()
       avl <= th1 ? last.BlankClip() : avl >= th2 ? last.BlankClip(color=color_white) : last
    """, args="th1,th2", local=true)
}

This is much easier than the standard approach of dynamically building the runtime script using string concatenation, or passing the values via global variables.

Because the run-time script is evaluated in its own scope, there is now no problem in calling bracket_luma more than once in the same script (previously the variables th1 and th2 of different instances could interfere with each other).


Run-time Filters

GRunT provides extended versions of the following run-time filters:

ScriptClip

ScriptClip(clip clip, string filter [, bool showx, bool after_frame, string args, bool local])
GScriptClip(clip clip, string filter [, bool show, bool after_frame, string args, bool local])

FrameEvaluate

FrameEvaluate(clip clip, string filter, [, bool showx, bool after_frame, string args, bool local])
GFrameEvaluate(clip clip, string filter [, bool show, bool after_frame, string args, bool local])

ConditionalFilter

ConditionalFilter(clip testclip, clip source1, clip source2, string expression1, string operator, string expression2
     [, bool showx, string args, bool local])

GConditionalFilter(clip testclip, clip source1, clip source2, string expression1, string operator, string expression2
     [, bool show, string args, bool local])

ConditionalFilter(clip testclip, clip source1, clip source2, string expression
     [, bool showx, string args, bool local])

GConditionalFilter(clip testclip, clip source1, clip source2, string expression
     [, bool show, string args, bool local])

WriteFile

WriteFile(clip clip, string filename, string expression1 [, string expression2 [, ...]]
     [, bool append, bool flush, string args, bool local])

GWriteFile(clip clip, string filename, string expression1 [, string expression2 [, ...]]
     [, bool append, bool flush, string args, bool local])

WriteFileIf

WriteFileIf(clip clip, string filename, string expression1 [, string expression2 [, ...]]
     [, bool append, bool flush, string args, bool local])

GWriteFileIf(clip clip, string filename, string expression1 [, string expression2 [, ...]]
     [, bool append, bool flush, string args, bool local])

The alternative (G*) names may be used if you wish, but this is optional in AviSynth version 2.58 or later.


Each filter is 100% backwards compatible with its standard equivalent, but has two additional optional arguments:

  • string args: the variables whose values are to be imported into the run-time script, written as a list of names separated by commas. The given variable names are evaluated in the current (compile-time) context, so can include function parameters or local variables. Each value becomes the initial value of the corresponding variable at each invocation of the run-time script.
  • Elements of the args string can also take the form name=expression; the expression is evaluated in the current context and sets the value of the named variable.
Example:
args="x, y=n+1, c=c.Trim(2, 0)"
will set values for the variables x, y and c. Here y need not even exist in the current environment (although x, n and c must exist).
  • The simple form (without the expression) is just a shorthand for the more general form, with the variable name itself being used as the expression. So, for example,
args="x, y, z"
is equivalent to
args="x=x, y=y, z=z"
passing the values of the compile-time variables x, y and z (from outside the run-time script) into the variables of the same name inside the script.
  • Spaces may be freely used (or not) inside the args string, just as in Avisynth function calls.
  • bool local: if true, the filter will evaluate its run-time script in a new variable scope, avoiding unintended sharing of variables between run-time scripts. Default is true if args is also specified, otherwise false (to preserve backwards compatibility).

TODO - document show, showx


Run-time Functions

The plugin also provides the following extensions to the run-time functions (such as AverageLuma):

  • These functions can now be called inside a user function, when (and only when) the user function is called from a run-time script.
  • Each function has a new optional int argument, which can be used to get the value from another frame, relative to the current one.For example, AverageLuma(-1) returns the value for the previous frame.

Note that to support the first feature, current_frame is now a global variable (see discussion). However, the second feature means that it is no longer necessary to change current_frame to access other frames. In fact, for most purposes, you can forget that current_frame exists as an explicit variable.

Here is an example of a weighted second order luma interpolation function:

function InterpLuma2(clip c) {
    lm_k = AverageLuma(c)
    lm_km1 = AverageLuma(c, -1)
    lm_kp1 = AverageLuma(c, 1)
    dvg = (lm_km1 - 2 * lm_k + lm_kp1) / 2
    return lm_k + Sign(dvg) * Sqrt(Abs(dvg))
}

This function can be called from any run-time script. Previously, something like this this had to be done by assigning to current_frame (or using additional filters, eg Trim(1,0)), and the code had to be written directly in the run-time script rather than in a function.

In effect, we are now able to write run-time functions of our own, derived from the standard ones. Here is another example:

function AverageRed(clip c) {
    return RGBDifference(ShowRed(c), BlankClip(c))
}

Note too that, while useful in its own right, the ability to call run-time functions in a user function gives you more than just that. For the first time, it allows an entire run-time script to be put inside a function body, called for example like this:

ScriptClip("MyFunc()")

As the function body will be evaluated in a separate scope, this is another way of eliminating the problem of unintended sharing of variables between run-time scripts. However, you may prefer to write the run-time script 'in-line' and invoke the run-time filter with local=true.


Here is the complete list of run-time functions, with their extended interface.

Average
AverageLuma (clip [, int offset])
AverageChromaU (clip [, int offset])
AverageChromaV (clip [, int offset])
Difference
RGBDifference (clip1, clip2 [, int offset])
LumaDifference (clip1, clip2 [, int offset])
ChromaUDifference (clip1, clip2 [, int offset])
ChromaVDifference (clip1, clip2 [, int offset])
Difference from previous
RGBDifferenceFromPrevious (clip [, int offset])
YDifferenceFromPrevious (clip [, int offset])
UDifferenceFromPrevious (clip [, int offset])
VDifferenceFromPrevious (clip [, int offset])
Difference to next
RGBDifferenceToNext (clip [, int offset])
YDifferenceToNext (clip [, int offset])
UDifferenceToNext (clip [, int offset])
VDifferenceToNext (clip [, int offset])
Color plane median, min, max, range
YPlaneMax (clip, float threshold [, int offset])
UPlaneMax (clip, float threshold [, int offset])
PlaneMax (clip, float threshold [, int offset])
YPlaneMin (clip, float threshold [, int offset])
UPlaneMin (clip, float threshold [, int offset])
VPlaneMin (clip, float threshold [, int offset])
YPlaneMedian (clip [, int offset])
UPlaneMedian (clip [, int offset])
VPlaneMedian (clip [, int offset])
YPlaneMinMaxDifference (clip, float threshold [, int offset])
UPlaneMinMaxDifference (clip, float threshold [, int offset])
VPlaneMinMaxDifference (clip, float threshold [, int offset])

The optional offset parameter specifies the offset (which may be negative) from the current frame; default is zero.


ConditionalFilter

For added convenience, there is a new variant of ConditionalFilter which takes a single boolean expression instead of three separate parameters as at present. This is useful when the condition to be tested is a compound one or is already available in boolean form (like IsCombed()).

For example,

ConditionalFilter(c, c1, c2, "AverageLuma(c1) > AverageLuma() && AverageLuma(c1) > AverageLuma(c2)")

where previously you would have to say

ConditionalFilter(c, c1, c2, "AverageLuma(c1) > AverageLuma() && AverageLuma(c1) > AverageLuma(c2)", "=", 

Note that this form of ConditionalFilter also makes it easier use the relational operators <=, >= and !=, which are not supported as the operator in the standard ConditionalFilter.


Configuration

For the extended run-time filters, for compatibility reasons the default for local is false unless args is also specified. However, it is recommended to always use local=true unless you really need to communicate values of variables from one run-time script to another (note that you can always use global variables for this).

To this end, the plugin provides GRTConfig:

GRTConfig(bool local)

GRTConfig(local=true) sets local=true by default for all subsequent filters.


Changelog

  • v1.0.1 (Gavino, 27th September 2008):
- fix for Avisynth 2.5.7 (have to use alternative names for filters, eg GScriptClip)
  • v1.0.0 (Gavino, 9th July 2008):
- add 'args' and 'local' to filters
- run-time functions with offset from current_frame
- new variant of ConditionalFilter (single boolean expr)
  • v0.1 (Gavino, 18th June 2008):
- fix Avisynth bug in setting of current_frame
- make current_frame global (allows run-time functions to be cslled inside user functions)


Archived Downloads

Version Download Mirror
v1.0.1 GRunT101.zip


Document v1.0.1 (Gavino, 27th September 2008)


Back to External Filters

Personal tools