GRunT

From Avisynth wiki
(Difference between revisions)
Jump to: navigation, search
(GRunT)
 
(add external links section)
 
(12 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{FilterCat|External_filters|Plugins|Support_filters}}
+
<div style="max-width:62em" >
 +
{{FilterCat4|External_filters|Plugins|Plugins_x64|Support_filters}}
 
{{Filter3
 
{{Filter3
| Gavino
+
| {{Author/Gavino}}, {{Author/pinterf}}
| v1.0.1
+
| v1.0.2
| 3=[http://forum.doom9.org/attachment.php?s=e3dfd39b17aff991b34523778ca798f5&attachmentid=8852&d=1222533692 GRunT101.zip]
+
| 3=[https://github.com/pinterf/GRunT/releases GRunT-v1.02.7z]
| 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>
+
</div>
 
== 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]].
+
<div style="max-width:62em" >
 +
[[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>
 +
</div>
 
==Features==
 
==Features==
 +
<div style="max-width:62em" >
 
* Simple, natural and robust way to pass variables into a run-time script from 'outside'
 
* 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
 
* 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 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
+
* [[#ConditionalFilter2|New variant of ConditionalFilter]] with a single boolean expression
* Fixes a fairly serious bug in the run-time system
+
<!-- NOT SURE IF CURRENT INFO
* Lightweight plugin extending the standard run-time environment, minimal time and memory overhead
+
* 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
 
* 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>
== [[Script variables|Syntax and Parameters]] ==
+
</div>
 +
== Requirements ==
 +
* [x86] [[AviSynth+]] or [https://sourceforge.net/projects/avisynth2/ AviSynth 2.6.0]
 +
* [x64] [[AviSynth+]]
 +
* Supported color formats: All
 +
<br>
 +
== A variables scope and lifetime example ==
 +
<div style="max-width:62em" >
 +
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).
 +
</div>
  
===Run-Time filters:===
 
The plugin provides extended versions of the following run-time filters:
 
* [[ScriptClip#ScriptClip|ScriptClip]]
 
:<code>ScriptClip(clip, string, bool "showx", bool "after_frame", string "args", bool "local")</code>
 
:<code>GScriptClip(clip, string, bool "show", bool "after_frame", string "args", bool "local")</code>
 
* [[FrameEvaluate#FrameEvaluate|FrameEvaluate]]
 
:<code>FrameEvaluate(clip, string, bool "showx", bool "after_frame", string "args", bool "local")</code>
 
:<code>GFrameEvaluate(clip, string, bool "show", bool "after_frame", string "args", bool "local")</code>
 
* [[ConditionalFilter]]
 
:<code>ConditionalFilter(clip, clip, clip, string, bool "showx", string "args", bool "local")</code>
 
:<code>ConditionalFilter(clip, clip, clip, string, string, string, bool "showx", string "args", bool "local")</code>
 
:<code>GConditionalFilter(clip, clip, clip, string, bool "show", string "args", bool "local")</code>
 
:<code>GConditionalFilter(clip, clip, clip, string, string, string, bool "show", string "args", bool "local")</code>
 
* [[WriteFile]]
 
:<code>WriteFile(clip, string "filenamex", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")</code>
 
:<code>GWriteFile(clip, string "filename", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")</code>
 
* [[WriteFileIf]]
 
:<code>WriteFileIf(clip, string "filenamex", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")</code>
 
:<code>GWriteFileIf(clip, string "filename", string, ..., string, ..., bool "append", bool "flush", string "args", bool "local")</code>
 
  
 +
== Run-time Filters ==
 +
<div style="max-width:62em" >
 +
'''GRunT''' provides extended versions of the following run-time filters:
 +
===== ''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>
 +
:''cf. AviSynth internal function ''[[ConditionalFilter#ScriptClip|ScriptClip]]
  
The alternative names <code>GScriptClip, GFrameEvaluate, GConditionalFilter, GWriteFile</code> and <code>GWriteFileIf</code> may also be used. However, if running on version '''2.57 or earlier''' of AviSynth, then '''only''' the alternative names may be used.<br>(This restriction is necessary for technical reasons - sorry about that.)
+
===== ''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>
 +
:''cf. AviSynth internal function ''[[ConditionalFilter#FrameEvaluate|FrameEvaluate]]
 +
 
 +
===== ''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>
 +
:''cf. AviSynth internal function ''[[ConditionalFilter#ConditionalFilter|ConditionalFilter]]
 +
 
 +
===== ''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>
 +
:''cf. AviSynth internal function ''[[WriteFile]]
 +
 
 +
===== ''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>
 +
:''cf. AviSynth internal function ''[[WriteFileIf]]
 +
 
 +
 
 +
The alternative ({{FuncDef|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:
 
Each filter is 100% backwards compatible with its standard equivalent, but has two additional optional arguments:
  
:*<code>string args</code>: 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.
:*<code>bool local</code>: 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).
+
<div {{NotaBeneWidthIndent|50|4|0px solid black}} >
 +
*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).
  
A short example (based on the original) shows how this greatly simplifies passing function parameters into a run-time script.
+
*The simple form (without ''=expression'') is just a shorthand for the more general form, with the variable name itself being used as the expression. So, for example,
<pre>function bracket_luma(clip c, float th1, float th2) {
+
<pre style="width:20em;margin:0 0 0 3em;padding:0;border:none;">
  Assert(0 <= th1 && th1 < th2 && th2 <= 255, "Invalid thresholds!")
+
args="x, y, z"
  ScriptClip(c, """
+
</pre>
    avl = AverageLuma()
+
:is equivalent to
    avl <= th1 ? last.BlankClip() : avl >= th2 ? last.BlankClip(color=color_white) : last
+
<pre style="width:20em;margin:0 0 0 3em;padding:0;border:none;">
  """, args="th1,th2", local=true)
+
args="x=x, y=y, z=z"
}</pre>
+
</pre>
This is much easier than the standard approach of dynamically building the runtime script using string concatenation, or passing the values via global variables.
+
: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.
  
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).  
+
*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.
 +
</div>
 +
 
 +
:*''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).
 +
 
 +
:*As in the AviSynth internal counterparts, {{FuncArg|show}} (or {{FuncArg|showx}}) to true will display the actual values on the screen.
 +
</div>
 +
 
 +
 
 +
== Run-time Functions ==
 +
<div style="max-width:62em" >
 +
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.
 +
 
 +
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>
 +
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>
 +
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.
 +
</div>
 +
 
 +
 
 +
<div id="ConditionalFilter2">
 +
== ConditionalFilter ==
 +
<div style="max-width:62em" >
 +
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)",
 +
\ "==", "true")
 +
 
 +
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.
 +
-->
 +
</div>
 +
</div>
 +
 
 +
 
 +
== Configuration ==
 +
<div style="max-width:62em" >
 +
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.
 +
</div>
  
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):
+
<div style="max-width:62em" >
- fix for Avisynth 2.5.7 (have to use alternative names for filters, eg GScriptClip)
+
*v1.0.2 (pinterf 30th April 2020):
 +
:-AviSynth 2.6 Interface
 +
:-Register as [[MT_NICE_FILTER]] for AviSynth+
 +
*v1.0.1a (yesmanitsbearman, 17th May 2016):
 +
:- fix compilation with AviSynth+
 +
:- 64-bit binary compiled with Microsoft Visual Studio C++ 2015.
 +
:- [https://forum.doom9.org/showthread.php?p=1767990#post1767990 Doom9 post]
 +
 
 +
*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):
+
*v1.0.0 (Gavino, 9th July 2008):
- add 'args' and 'local' to filters
+
:- add 'args' and 'local' to filters
- run-time functions with offset from current_frame
+
:- run-time functions with offset from current_frame
- new variant of ConditionalFilter (single boolean expr)
+
:- new variant of ConditionalFilter (single boolean expr)
  
v0.1 (Gavino, 18th June 2008):
+
*v0.1 (Gavino, 18th June 2008):
- fix Avisynth bug in setting of current_frame
+
:- fix Avisynth bug in setting of current_frame
- make current_frame global (allows run-time functions to be cslled inside user functions)</pre>
+
:- make current_frame global (allows run-time functions to be cslled inside user functions)
 +
</div>
 
<br>
 
<br>
 
== Archived Downloads ==
 
== Archived Downloads ==
 +
<div style="max-width:62em" >
 
{| class="wikitable" border="1"; width="600px"
 
{| class="wikitable" border="1"; width="600px"
 
|-
 
|-
Line 100: Line 289:
 
|-
 
|-
 
!v1.0.1
 
!v1.0.1
|[http://forum.doom9.org/attachment.php?s=e3dfd39b17aff991b34523778ca798f5&attachmentid=8852&d=1222533692 GRunT101.zip]
+
|[https://forum.doom9.org/attachment.php?s=e3dfd39b17aff991b34523778ca798f5&attachmentid=8852&d=1222533692 GRunT101.zip]
|
+
|[https://web.archive.org/web/20200523170646if_/https://files.videohelp.com/u/223002/GRunT101.zip GRunT101.zip]
 
|-
 
|-
 
|}
 
|}
 +
</div>
 
<br>
 
<br>
==External Links ==
+
== External Links ==
 +
*[https://github.com/pinterf/GRunT GitHub] - Source code repository.
 
<br>
 
<br>
 
<br>
 
<br>
 
-----------------------------------------------
 
-----------------------------------------------
 
'''Back to [[External_filters#Support_filters|External Filters]] &larr;'''
 
'''Back to [[External_filters#Support_filters|External Filters]] &larr;'''

Latest revision as of 17:07, 23 May 2020

Abstract
Author Gavino, pinterf
Version v1.0.2
Download GRunT-v1.02.7z
Category Support filters
License GPLv2
Discussion Doom9 Thread

Contents

[edit] 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.

[edit] 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)
  • New variant of ConditionalFilter with a single boolean expression
  • 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).

[edit] Requirements


[edit] 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).


[edit] Run-time Filters

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

[edit] 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])

cf. AviSynth internal function ScriptClip
[edit] 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])

cf. AviSynth internal function FrameEvaluate
[edit] 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])

cf. AviSynth internal function ConditionalFilter
[edit] 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])

cf. AviSynth internal function WriteFile
[edit] 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])

cf. AviSynth internal function WriteFileIf


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 =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).
  • As in the AviSynth internal counterparts, show (or showx) to true will display the actual values on the screen.


[edit] 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.

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


[edit] 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)", 
\ "==", "true")

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.


[edit] 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.


[edit] Changelog

  • v1.0.2 (pinterf 30th April 2020):
-AviSynth 2.6 Interface
-Register as MT_NICE_FILTER for AviSynth+
  • v1.0.1a (yesmanitsbearman, 17th May 2016):
- fix compilation with AviSynth+
- 64-bit binary compiled with Microsoft Visual Studio C++ 2015.
- Doom9 post
  • 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)


[edit] Archived Downloads

Version Download Mirror
v1.0.1 GRunT101.zip GRunT101.zip


[edit] External Links

  • GitHub - Source code repository.




Back to External Filters

Personal tools