GRunT: Difference between revisions

From Avisynth wiki
Jump to navigationJump to search
Raffriff42 (talk | contribs)
m add links, use Template:FuncDef, Template:BoxWidthIndent more TODO
Raffriff42 (talk | contribs)
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.
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|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>


===Run-Time filters:===
===== ''[[WriteFile]]'' =====
The plugin provides extended versions of the following run-time filters:
<div {{BoxWidthIndent|70|2}} >
* [[ScriptClip#ScriptClip|ScriptClip]]
{{Func2Def
:{{FuncDef|ScriptClip(clip, string, bool "showx", bool "after_frame", string "args", bool "local")}}
|WriteFile(clip ''clip'', string ''filename'', string ''expression1'' [, string ''expression2'' [, ...]]
:{{FuncDef|GScriptClip(clip, string, bool "show", bool "after_frame", string "args", bool "local")}}
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''append'', bool ''flush'', string ''args'', bool ''local''])
* [[FrameEvaluate#FrameEvaluate|FrameEvaluate]]
|GWriteFile(clip ''clip'', string ''filename'', string ''expression1'' [, string ''expression2'' [, ...]]  
:{{FuncDef|FrameEvaluate(clip, string, bool "showx", bool "after_frame", string "args", bool "local")}}
<br>&nbsp;&nbsp;&nbsp;&nbsp; [, bool ''append'', bool ''flush'', string ''args'', bool ''local''])}}
:{{FuncDef|GFrameEvaluate(clip, string, bool "show", bool "after_frame", string "args", bool "local")}}
</div>
* [[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>
===== ''[[WriteFileIf]]'' =====
(This restriction is necessary for technical reasons - sorry about that.)
<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}}
== 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, <tt>AverageLuma(-1)</tt> returns the value for the previous frame.


A short example (based on the original) shows how this greatly simplifies passing function parameters into a run-time script.
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.
<div {{BoxWidthIndent|60|2}}>
 
  function bracket_luma(clip c, float th1, float th2) {
Here is an example of a weighted second order luma interpolation function:
    Assert(0 <= th1 && th1 < th2 && th2 <= 255, "Invalid thresholds!")
<div {{BoxWidthIndent|40|1}}>
    ScriptClip(c, """
  function InterpLuma2(clip c) {
      avl = AverageLuma()
    lm_k = AverageLuma(c)
      avl <= th1 ? last.BlankClip() : avl >= th2 ? last.BlankClip(color=color_white) : last
    lm_km1 = AverageLuma(c, -1)
    """, args="th1,th2", local=true)
    lm_kp1 = AverageLuma(c, 1)
    dvg = (lm_km1 - 2 * lm_k + lm_kp1) / 2
    return lm_k + Sign(dvg) * Sqrt(Abs(dvg))
}
</div>
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:  
<div {{BoxWidthIndent|40|1}}>
function AverageRed(clip c) {
    return RGBDifference(ShowRed(c), BlankClip(c))
  }
  }
</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.
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''.
 
 
Here is the complete list of [[Internal_functions/Runtime_functions#Runtime_functions|run-time functions]], with their extended interface.
===== [[Internal_functions/Runtime_functions#Average|Average]] =====
:<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).  


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).
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.


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>
Example: <code>args="x, y=n+1, c=c.Trim(2, 0)"</code> will provide values for the variables x, y and c.<br>
Here y need not even exist in the current environment (although x, n and c must).


<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


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(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(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(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(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(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.

AverageLuma (clip [, int offset])
AverageChromaU (clip [, int offset])
AverageChromaV (clip [, int offset])
RGBDifference (clip1, clip2 [, int offset])
LumaDifference (clip1, clip2 [, int offset])
ChromaUDifference (clip1, clip2 [, int offset])
ChromaVDifference (clip1, clip2 [, int offset])
RGBDifferenceFromPrevious (clip [, int offset])
YDifferenceFromPrevious (clip [, int offset])
UDifferenceFromPrevious (clip [, int offset])
VDifferenceFromPrevious (clip [, int offset])
RGBDifferenceToNext (clip [, int offset])
YDifferenceToNext (clip [, int offset])
UDifferenceToNext (clip [, int offset])
VDifferenceToNext (clip [, int offset])
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