Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

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

Reply
 
Thread Tools Search this Thread Display Modes
Old 18th June 2009, 11:18   #1  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
GScript - language extensions for Avisynth

This is something I started as a 'proof of concept' for my own amusement.
As I think some people will find it useful, I am making it generally available.

GScript is a plugin that extends the Avisynth scripting language to provide additional control-flow constructs:
multi-line conditionals (if-then-else blocks), 'while' loops and 'for' loops.
Rather than trying to simulate these constructs with functions, GScript effectively extends the language syntax, making it easy to use the new constructs in a natural way and in arbitrary combinations.

Here are the constructs in detail:

'if' statement
Code:
if ( condition ) {
  statements
}
else {
  statements
}
where condition is any boolean expression.
The statements can be any Avisynth statements, including the GScript extensions themselves, and so the new constructs can be nested.
The else part may be omitted (equivalent to else {}).

GScript also provides the 'else if' construct (optionally repeated to create a chain of conditionals). Thus
Code:
if ( condition ) {
  statements
}
else if ( condition ) {
  statements
}
else if (...) { ... }
...
else {
  statements
}
'while' loop
Code:
while ( condition ) {
  statements
}
The statements are repeated while the condition is true.

Example:
Code:
while (Height() < h) {
  StackVertical(last, c) 
}
'for' loop
Code:
for ( variable = init , limit , step ) {
  statements
}
init, limit and step are integer expressions, with step non-zero. step is optional and defaults to 1.

First the variable is set to the value of init.
The statements are repeated until the exit condition is met,
ie variable exceeds limit (if step > 0), or is less then limit (if step < 0).
After each iteration, variable is incremented by step.
If the initial value satisfies the exit condition, the number of iterations will be zero.

Example:
Code:
for (i=1, nBlurs) {
  Blur(0.5)
}
Using GScript
Once the plugin is loaded (either via LoadPlugin or by installing GScript.dll in your plugins folder), there are two ways to use the extended language features.
Firstly, a script (or part of a script) containing extensions can be passed as a text string to the GScript function (similar to the way functions like ScriptClip or MT are used). For example,
Code:
GScript("""
if (i > 10) {
  x = 1
  y = 2
  z = 3
}
else {
  x = 4
  y = 5
  z = 6
}
""")
The second way is to use the GImport function, which reads the entire contents of a file. This is similar to the standard Import, but supports the use of GScript extensions directly in the file.
The advantage of this is that you don't have to put quotes around the script, or worry about possible problems if the embedded script itself contains both triple and single quotes.
Thus, you can write entire scripts directly in the extended language and just pass to Avisynth a single GImport command to read it.
Code:
GImport("MyGScript.avs")
For completeness, there is also a function GEval, analagous to the standard Eval, which evaluates an arbitrary string that is permitted to contain GScript extensions.

Update: Version 1.1 (GScript_11.zip) released 6th Dec 2009
Attached Files
File Type: zip GScript_11.zip (76.1 KB, 4549 views)

Last edited by Gavino; 15th February 2010 at 13:58. Reason: Remove v1.0 dll from attachments
Gavino is offline   Reply With Quote
Old 18th June 2009, 11:51   #2  |  Link
J_Darnley
Registered User
 
J_Darnley's Avatar
 
Join Date: May 2006
Posts: 957
Good god man! This is brilliant.
__________________
x264 log explained || x264 deblocking how-to
preset -> tune -> user set options -> fast first pass -> profile -> level
Doom10 - Of course it's better, it's one more.
J_Darnley is offline   Reply With Quote
Old 18th June 2009, 13:48   #3  |  Link
leeperry
Kid for Today
 
Join Date: Aug 2004
Posts: 3,477
nice! so basically this could be used w/ mod2 only scripts? if not mod2 > add padding lines?
leeperry is offline   Reply With Quote
Old 18th June 2009, 14:11   #4  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,389
Quote:
Originally Posted by leeperry View Post
nice! so basically this could be used w/ mod2 only scripts? if not mod2 > add padding lines?
Sure, it could. You could also buy a laser beam cutting machine when you need to cut a piece of paper.

For *such* a simple task, Avisynth's standard language (conditional operation through bool ? this : that) is fully sufficient ...

Code:
src = last

dest_modulo = 2    #  or 4, 6, 8, 1337, ...
src_modulo  = src.width()%dest_modulo
padding     = dest_modulo - src_modulo

src_modulo==0 ? src : src.addborders(0,0,padding,0)
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 18th June 2009, 14:20   #5  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by leeperry View Post
nice! so basically this could be used w/ mod2 only scripts? if not mod2 > add padding lines?
Yes, although you could probably do this just as easily with the standard conditional operator (... ? ... : ... ).
EDIT: as Didée has just shown!

Where the extended 'if' becomes really useful is when you need to write more than one statement in one of the conditional 'branches'.
Without GScript, you are limited to the rather messy techniques described here, which can't be easily nested. See also here.

Last edited by Gavino; 18th June 2009 at 14:22. Reason: Didée's answer
Gavino is offline   Reply With Quote
Old 18th June 2009, 14:31   #6  |  Link
Archimedes
Registered User
 
Join Date: Apr 2005
Posts: 213
If then constructs can also be realized in this way.

Code:
isYV12() ? Eval("""
  # do
  # something
""") : Eval("""
  # do
  # something
""")
Archimedes is offline   Reply With Quote
Old 18th June 2009, 15:58   #7  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
Very nice indeed! This way of coding in a more readable syntax(plus the extra functions) is more that welcome. One could hope that this would eventually be implemented in Avisynth so the quotes around the script would not be needed at all.
__________________
DVD slideshow GUI(Freeware).
tin3tin is offline   Reply With Quote
Old 18th June 2009, 18:00   #8  |  Link
leeperry
Kid for Today
 
Join Date: Aug 2004
Posts: 3,477
hehe ok thanks fellas, as we say in France "caviar doesn't taste better w/ a big spoon"...ideally I'd love to an automatic script that'd make everything mod2 in ffdshow by simply adding horizontal black bars *only* if required, I'll look into Didée's script
leeperry is offline   Reply With Quote
Old 18th June 2009, 20:39   #9  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
Gavino, thanks for doing this! It makes script development a lot simpler now
mikeytown2 is offline   Reply With Quote
Old 18th June 2009, 21:04   #10  |  Link
shoopdabloop
Registered User
 
Join Date: Mar 2009
Posts: 166
finally, as an actionscript 3 programmer, i can feel a little more comfortable in avisynth.
shoopdabloop is offline   Reply With Quote
Old 19th June 2009, 17:16   #11  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by tin3tin View Post
One could hope that this would eventually be implemented in Avisynth so the quotes around the script would not be needed at all.
If the extensions gain sufficient acceptance, it would be fairly trivial to put them into the Avisynth core.

To implement the plugin, I used a modified version of the Avisynth parser code. The changes are relatively self-contained and all clearly marked in my source code. It would take little more than a cut-and-paste job to put those changes into the 'real' parser.
Gavino is offline   Reply With Quote
Old 25th June 2009, 23:50   #12  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
(I know that it ain't xmas - but imagine what you could do with those functions combined with two new functions(just idears): one to paint a pixel(x,y,color) and one to read the color of a pixel(x,y) then the more complicated imagemanipulation filters could be prototyped in avisynth.)

Anyway thanks again for the Gscript plugin.
__________________
DVD slideshow GUI(Freeware).
tin3tin is offline   Reply With Quote
Old 18th September 2009, 21:25   #13  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
A bunch of gradients done with gscript.

Uncomment the various Gradient lines to check them out:
Code:
loadplugin("GScript.dll")

function Gradient(int gwidth, int gheight, int ared, int agreen, int ablue, int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
blankclip(1,gwidth,1)
GScript("""
for (i=1, gheight,1){
    r=int(spline(i,0,ared,int(gheight/2),bred,gheight,cred,true)/float(gheight)*255)
    g=int(spline(i,0,agreen,int(gheight/2),bgreen,gheight,cgreen,true)/float(gheight)*255)
    b=int(spline(i,0,ablue,int(gheight/2),bblue,gheight,cblue,true)/float(gheight)*255)
    c=blankclip(1,720,1,color=r*65536 + g*256 + b)
    StackVertical(last, c)
}
""")
crop(0,1,0,0)
}
function GradientNoSpline(int gwidth, int gheight, int ared, int agreen, int ablue, int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
blankclip(1,gwidth,1)
GScript("""
for (i=1, gheight,1){
    r=int(spline(i,0,ared,int(gheight/2),bred,gheight,cred,false)/float(gheight)*255)
    g=int(spline(i,0,agreen,int(gheight/2),bgreen,gheight,cgreen,false)/float(gheight)*255)
    b=int(spline(i,0,ablue,int(gheight/2),bblue,gheight,cblue,false)/float(gheight)*255)
    c=blankclip(1,720,1,color=r*65536 + g*256 + b)
    StackVertical(last, c)
}
""")
crop(0,1,0,0)
}

#Gradient(720, 576,86,107,103,184,164,126,140,36,29)#Vintage America
#Gradient(720, 576,59,61,40,113,117,76,255,113,68)#Dawn
#Gradient(720, 576,160, 88, 50, 209,169, 75, 249,209,140)#fruity
#Gradient(720, 576,225,230,250,171,200,226,24,49,82)#Blue
#Gradient(720, 576,236,224,158,145,134,90,191,62,47)
#Gradient(720, 576, 62,102,51,220,240,242,150,35,9)#GreenBlueRed
#Gradient(720, 576,62,153,96,159,235,74,237,255,116)#Greenish
#Gradient(720, 576,117,0,0,215,215,215,0,100,200)#BleuBancRouge
#Gradient(720, 576,178,255,0,194,194,194,255,96,10)#GreenBlueRed
#Gradient(720, 576,118,192,245,223,236,245,245,105,198)#Baby
#Gradient(720, 576,118,192,245,255,170,85,255,0,0)#Sunset
#Gradient(720, 576, 17,0,28,94,0,30,17,9,28)#RedPurple
#Gradient(720, 576, 6,171,170,5,91,161,0,28,54)#Deep Ocean
#Gradient(720, 576,217,204,143,109,140,42,37,64,25)#Grassy Fields
#Gradient(720, 576,103,57,15,217,139,43,42,23,12)#Brown
#Gradient(720, 576,178,150,82,255,94,53,166,222,161)#OrangeGreen
#Gradient(720, 576,249,209,147,75,83,106,193,90,55)#Blue Evening
GradientNoSpline(720, 576,121,121,59,216,186,72,51,7,6)#Red jungle
__________________
DVD slideshow GUI(Freeware).

Last edited by tin3tin; 18th September 2009 at 21:31.
tin3tin is offline   Reply With Quote
Old 19th September 2009, 09:47   #14  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Thanks, tin3tin. A good example of how GScript makes this sort of thing easier to write.

Of course, it can also be done in standard Avisynth by using recursive procedures, but most people would find it more natural to write an iterative construction like this directly as a loop.

Note that the GScript call need not be confined to the 'non-standard' parts of the script. For example, each function (or even both together) could be put inside GScript. This way, the GScript parser is invoked only once, rather than on each call to the function.

For example,
Code:
GScript("""
function Gradient( ... ) {
  ...
}

function GradientNoSpline( ... ) {
  ...
}
""")
Gavino is offline   Reply With Quote
Old 19th September 2009, 09:56   #15  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
Will that make it faster? As it is this gradient function is properly too slow(thanks to stackvertical?) to be really useful.
__________________
DVD slideshow GUI(Freeware).
tin3tin is offline   Reply With Quote
Old 19th September 2009, 10:48   #16  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
In principle, moving the GScript to outside the function declaration will speed up compilation of the function calls (and hence script loading), but the difference is unlikely to be noticeable. It doesn't affect the 'run-time' - GScript acts purely at 'compile-time'.

I'm not sure if the slowness here comes from the StackVertical or the Spline function - I will look into it and see if it can be made faster in some way.

In your code
Code:
r=int(spline(i,0,ared,int(gheight/2),bred,gheight,cred,true)/float(gheight)*255)
... etc ...
why do you effectively multiply by 255/gheight?
I get better results with just r=int(spline(...))
Gavino is offline   Reply With Quote
Old 20th September 2009, 09:30   #17  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
Quote:
why do you effectively multiply by 255/gheight?
I get better results with just r=int(spline(...))
You're right, that's just a leftover from previous attempt I forgot to clean out.
__________________
DVD slideshow GUI(Freeware).
tin3tin is offline   Reply With Quote
Old 20th September 2009, 17:04   #18  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
tin3tin - Looking at this more closely, I think the overhead is due to the repeated use of StackVertical. For an image height of 576, you have 576 instances of StackVertical, each copying an average of 288 lines, so that's over 150000 lines being copied!

A faster way would be to directly use a resizer as the interpolator instead of the Spline function. Try these alternative versions which should produce similar results to yours (I believe identical in the non-spline case).
Code:
function Gradient2(int gwidth, int gheight, int ared, int agreen, int ablue,
\          int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
  c1 = BlankClip(1, gwidth, 3, color=ared*65536 + agreen*256 + ablue)
  c2 = BlankClip(1, gwidth, 1, color=bred*65536 + bgreen*256 + bblue)
  c3 = BlankClip(1, gwidth, 3, color=cred*65536 + cgreen*256 + cblue)
  StackVertical(c1, c2, c3)
  Spline16Resize(gwidth, gheight, 0, 2.5, 0, -2.5)
}

function GradientNoSpline2(int gwidth, int gheight, int ared, int agreen, int ablue,
\          int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
  c1 = BlankClip(1, gwidth, 2, color=ared*65536 + agreen*256 + ablue)
  c2 = BlankClip(1, gwidth, 1, color=bred*65536 + bgreen*256 + bblue)
  c3 = BlankClip(1, gwidth, 2, color=cred*65536 + cgreen*256 + cblue)
  StackVertical(c1, c2, c3)
  BilinearResize(gwidth, gheight, 0, 1.5, 0, -1.5)
}
Here, GScript is no longer required, but I think it is fair to say that the problem lay not with GScript itself but with the method you used.

(BTW there was another bug in your original code, where 720 was used in place of gwidth in the BlankClips.)
Gavino is offline   Reply With Quote
Old 21st September 2009, 08:29   #19  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
Wow, that's clever - and fast!

Before it was impossible(too slow) to make a gradient lib like this(using 3 out of 5 colors from Kuler):
Code:
Gradient(720, 576,86,107,103,184,164,126,140,36,29).Subtitle("Vintage America", align=2,text_color=$FFFFFF)#Vintage America
last+Gradient(720, 576,59,61,40,113,117,76,255,113,68).Subtitle("Dawn", align=2,text_color=$FFFFFF)#Dawn
last+Gradient(720, 576,160, 88, 50, 209,169, 75, 249,209,140).Subtitle("Red Yellow Pink", align=2,text_color=$FFFFFF)#Red Yellow Pink
last+Gradient(720, 576,225,230,250,171,200,226,24,49,82).Subtitle("Blue", align=2,text_color=$FFFFFF)#Blue
last+Gradient(720, 576,236,224,158,145,134,90,191,62,47).Subtitle("White Green Red", align=2,text_color=$FFFFFF)#White Green Red
last+Gradient(720, 576, 62,102,51,220,240,242,150,35,9).Subtitle("Green White Red", align=2,text_color=$FFFFFF)#GreenWhiteRed
last+Gradient(720, 576,62,153,96,159,235,74,237,255,116).Subtitle("Greenish", align=2,text_color=$FFFFFF)#Greenish
last+Gradient(720, 576,117,0,0,215,215,215,0,100,200).Subtitle("Bleu Banc Rouge", align=2,text_color=$FFFFFF)#BleuBancRouge
last+Gradient(720, 576,178,255,0,194,194,194,255,96,10).Subtitle("Green Blue Red", align=2,text_color=$FFFFFF)#GreenBlueRed
last+Gradient(720, 576,118,192,245,223,236,245,245,105,198).Subtitle("Baby", align=2,text_color=$FFFFFF)#Baby
last+Gradient(720, 576,118,192,245,255,170,85,255,0,0).Subtitle("Sunset", align=2,text_color=$FFFFFF)#Sunset
last+Gradient(720, 576, 17,0,28,94,0,30,17,9,28).Subtitle("Red Purple", align=2,text_color=$FFFFFF)#RedPurple
last+Gradient(720, 576, 6,171,170,5,91,161,0,28,54).Subtitle("Deep Ocean", align=2,text_color=$FFFFFF)#Deep Ocean
last+Gradient(720, 576,217,204,143,109,140,42,37,64,25).Subtitle("Grassy Fields", align=2,text_color=$FFFFFF)#Grassy Fields
last+Gradient(720, 576,103,57,15,217,139,43,42,23,12).Subtitle("Brown", align=2,text_color=$FFFFFF)#Brown
last+Gradient(720, 576,178,150,82,255,94,53,166,222,161).Subtitle("Orange Green", align=2,text_color=$FFFFFF)#OrangeGreen
last+Gradient(720, 576,249,209,147,75,83,106,193,90,55).Subtitle("Blue Evening", align=2,text_color=$FFFFFF)#Blue Evening
last+GradientNoSpline(720, 576,121,121,59,216,186,72,51,7,6).Subtitle("Red jungle", align=2,text_color=$FFFFFF)#Red jungle
The next big challenge is how to make a smooth gradient in yv12.
__________________
DVD slideshow GUI(Freeware).

Last edited by tin3tin; 21st September 2009 at 09:04.
tin3tin is offline   Reply With Quote
Old 21st September 2009, 14:13   #20  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by tin3tin View Post
The next big challenge is how to make a smooth gradient in yv12.
I suppose you mean something other than just adding ConvertToYV12()?
Perhaps starting out with yuv values as the arguments instead of rgb?

Note that BlankClip has a color_yuv parameter, so I think you can just do something similar to the rgb version, using pixel_type="YUY2", and convert to YV12 after the resize.
Gavino is offline   Reply With Quote
Reply

Tags
for-loop, if-then-else, while-loop

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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

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

Forum Jump


All times are GMT +1. The time now is 11:46.


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