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 Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 2nd February 2014, 19:32   #1  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
"Superclip" objects idea - is this implementable, and where would I start?

Hi all, I've got yet another idea that slightly exceeds my knowledge of AviSynth's internals.

The idea is for "superclip" objects:

Code:
clip=avisource("source.avi")
s_clip=superclip(clip)
You could, for example, trim such a clip and get the trimmed video out:

Code:
s_clip.supertrim(50,150)
return s_clip.video
But the big difference with superclips is that you could also do things like this:

Code:
s_clip.untrim() # restore full length clip
s_clip.extend(50) # add another fifty frames to the end from the original clip
Because the trim state of the original clip is only stored in member variables it can be adjusted later.

Now, as I've said, I don't quite know AviSynth well enough yet to know if this is even possible, or where I'd start, so - could anyone give me some hints?

The only way I can think of at the moment is to add another audio track or extra video lines to store the data, but that doesn't seem very neat (and means the object is still just a clip as opposed to a new kind of object). Is it possible to create and operate on my own objects in this way?

Thanks!

David
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is online now   Reply With Quote
Old 4th February 2014, 19:55   #2  |  Link
ultim
AVS+ Dev
 
ultim's Avatar
 
Join Date: Aug 2013
Posts: 359
You can achieve similar effect right now with much less code:
Code:
s_clip=clip
clip.trim(50,150)
s_clip.extend(50)
Or did I miss something?
__________________
AviSynth+
ultim is offline   Reply With Quote
Old 4th February 2014, 21:33   #3  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
Quote:
Originally Posted by ultim View Post
You can achieve similar effect right now with much less code:
Code:
s_clip=clip
clip.trim(50,150)
s_clip.extend(50)
Or did I miss something?
I think you might have:

Quote:
Script error: there is no function named "extend"
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is online now   Reply With Quote
Old 5th February 2014, 00:22   #4  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
I suppose some mashup of "hidden" globals and Eval statements could be made to do this, with enough work... *searching*
Hang on, AVSLib has "containers" based on this idea:
http://avslib.sourceforge.net/tutorials/containers.html
You could make an AVSLib "array" consisting of a clip and some properties such as its original framecount, its current trim in & out, its original size & current cropping, etc...

I don't know if Gavino's GrunT and/or StainlessS' RT_Stats can do this trick as well, but would not be surprised...
raffriff42 is offline   Reply With Quote
Old 5th February 2014, 11:17   #5  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
That sounds like it might be what I need to do, thanks.

Quote:
Container types are implemented as specially delimited strings.
A clip becomes part of a string? I suspect I have a lot of learning to do...
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is online now   Reply With Quote
Old 5th February 2014, 14:45   #6  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
If I understand it correctly, ABSLib "arrays" can be thought of as user-defined types - they have data members, but not member functions as true objects do. So instead of s_clip.extend(50) you would call extend(s_clip, 50)

Last edited by raffriff42; 5th February 2014 at 14:56.
raffriff42 is offline   Reply With Quote
Old 5th February 2014, 16:27   #7  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by raffriff42 View Post
instead of s_clip.extend(50) you would call extend(s_clip, 50)
In the Avisynth language, these are the same - the parser interprets s_clip.extend(50) as extend(s_clip, 50).
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 6th February 2014, 05:57   #8  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
That's interesting Gavino, I had thought dot notation was for clip variables only, but you are correct as usual.

I went ahead and created a basic "clip object" using arrays for my own amusement, even though I can't see a compelling real-world case for such a thing. Maybe this code will serve as a starting point for something more interesting...
Code:
#avisynth

LoadModule("avslib", "array", "core")

## set a delimiter that is not a valid path character
ArrayDelimiterSet("|") 

#######################################
### basic clip object
### supports trim, untrim, crop and uncrop
###
### @raffriff42
### http://forum.doom9.org/showthread.php?t=170180
### http://avslib.sourceforge.net/tutorials/containers.html
###
### version 0.2.0 06-Feb-2014 
###     (added API ident, changed whenever updates break compatibility) 
#######################################

#######################################
### create the clip object
##
## @ path - source path of clip C (optional; suggested usage only)
## @ tag  - general purpose string (can be used for any purpose)
##
## NOTE: path & tag cannot contain the "|" (array delimiter) character.
##
function _CreateClipObject(clip C, String "path", String "tag")
{
    path = Default(path, "")
    tag  = Default(tag, "")

    Assert(FindStr(path, "|")==0, "_CreateClipObject: '|' not allowed in path")
    Assert(FindStr(tag, "|")==0, "_CreateClipObject: '|' not allowed in tag")

    return ArrayCreate(     /*  ID : DESCRIPTION */
    \    "BCO-0.2" ,        /*   0 : object type and API ident */
    \    C ,                /*   1 : underlying clip */
    \    path ,             /*   2 : optional source path, user-supplied */
    \    tag ,              /*   3 : general purpose tag, user-defined */
    \    0 ,                /*   4 : firstframe */
    \    C.FrameCount ,     /*   5 : framecount */
    \    0 ,                /*   6 : leftcolumn */
    \    C.Width ,          /*   7 : width */
    \    0 ,                /*   8 : toprow */
    \    C.Height           /*   9 : height */
    \ )
}

#######################################
### return array index for a named property
##
function _i(String name)
{
    return (name=="path")          ?  2 : 
    \      (name=="tag")           ?  3 :
    \      (name=="firstframe")    ?  4 :
    \      (name=="framecount")    ?  5 :
    \      (name=="leftcolumn")    ?  6 :
    \      (name=="width")         ?  7 :
    \      (name=="toprow")        ?  8 :
    \      (name=="height")        ?  9 :
    \      Assert(false, "_i: invalid property name")
}

#######################################
### get clip in its current trimmed & cropped state
##
function _Clip(val o)
{
    Assert(o.ArrayGet(0)=="BCO-0.2", "_Clip: object mismatch")

    ## debugging
    #MessageClip(String(o._prop("height")))
    #return PointResize(Width*16, Height*16)

    return o.ArrayGet(1)
    \  .Trim(o._prop("firstframe"), length=o._prop("framecount"))
    \  .Crop(o._prop("leftcolumn"), o._prop("toprow"),
    \        o._prop("width"), o._prop("height"))
}

#######################################
### return a named property for a clip object
##
function _prop(val o, String name)
{
    Assert(o.ArrayGet(0)=="BCO-0.2", "_prop: object mismatch")

    return o.ArrayGet(_i(name))
}

#######################################
### perform basic Trim on a clip object, relative to its current state
##
function _TrimRelative(val o, int "delta_start", int "delta_count")
{
    Assert(o.ArrayGet(0)=="BCO-0.2", "_TrimRelative: object mismatch")

    delta_start = Default(delta_start, 0)
    delta_count = Default(delta_count, 0)

    c      = o.ArrayGet(1) ## underlying clip 
    cfirst = o._prop("firstframe")
    ccount = o._prop("framecount")

    newfirst = Min(Max(0, cfirst+delta_start), c.framecount-1)
    newlast  = Min(Max(newfirst, newfirst+ccount+delta_count), c.framecount)

    o = o.ArraySet(_i("firstframe"), newfirst)
    \    .ArraySet(_i("framecount"), newlast-newfirst)

    return o
}

#######################################
### perform basic Crop on a clip object, relative to its current state
##
function _CropRelative(val o, int "delta_x", int "delta_y", 
\                      int "delta_w", int "delta_h")
{
    Assert(o.ArrayGet(0)=="BCO-0.2", "_CropRelative: object mismatch")

    delta_x = Default(delta_x, 0)
    delta_y = Default(delta_y, 0)
    delta_w = Default(delta_w, 0)
    delta_h = Default(delta_h, 0)

    c  = o.ArrayGet(1) ## underlying clip 
    cx = o._prop("leftcolumn")
    cy = o._prop("toprow")
    cw = o._prop("width")
    ch = o._prop("height")

    new_x  = Min(Max(0, cx+delta_x), c.width-1)
    new_x2 = Min(Max(new_x+1, new_x+cw+delta_w), c.width)

    new_y  = Min(Max(0, cy+delta_y), c.height-1)
    new_y2 = Min(Max(new_y+1, new_y+ch+delta_h), c.height)

    o = o.ArraySet(_i("leftcolumn"), new_x)
    \    .ArraySet(_i("width"),      new_x2-new_x)
    \    .ArraySet(_i("toprow"),     new_y)
    \    .ArraySet(_i("height"),     new_y2-new_y)

    return o
}

#######################################
### set clip object's "tag" property
##  * a "tag" is a general purpose string (can be used for any purpose)
##  * thin wrapper for 'o.ArraySet(_i("tag"), tag)'
##  * if argument contains "|" (array delimiter), an error results. 
##
function _set_tag(val o, String tag)
{
    Assert(o.ArrayGet(0)=="BCO-0.2", "_set_tag: object mismatch")
    Assert(FindStr(tag, "|")==0, "_set_tag: '|' not allowed")

    o = o.ArraySet(_i("tag"), tag)
    return o
}

##################### TESTS #####################

## RGB32, 1280x720, 29.97, 2576 frames
path = "D:\VideoProjects\work\port-imperial-01 huf.avi"

C = AviSource(path)
\    .ShowFrameNumber

o = _CreateClipObject(C, path)

#o = o._TrimRelative(10, -20) ## starts @ 10, shorter by 20
#return o._Clip.Info

o = o._TrimRelative(10, -20) ## starts @ 10, shorter by 20
o = o._TrimRelative(-5, +10) ## starts @  5, shorter by 10
#return o._Clip.Info

#o = o._CropRelative(80, 80, 0, 0) ## 1200x640 
#return o._Clip.Info

#o = o._CropRelative(80, 80, -160, -160) ## 1120x560
#return o._Clip.Info

#o = o._CropRelative(80, 80, 0, 0) ## 1200x640 
#o = o._CropRelative(80, 80, -160, -160) ## 1040x480
#return o._Clip.Info

o = o._CropRelative(80, 80, 0, 0) ## 1200x640 
o = o._CropRelative(80, 80, -160, -160) ## 1040x480
o = o._CropRelative(-120, -120, 120, 120) ## 1160x600 
return o._Clip.Info
(EDIT simply having "path" and "tag" properties available may be more useful than "un-trimming")

Last edited by raffriff42; 7th February 2014 at 01:18. Reason: version 0.2.0
raffriff42 is offline   Reply With Quote
Old 7th February 2014, 00:01   #9  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
Wow, thanks raffriff, I wasn't expecting to anyone to do my homework for me!

Quote:
I can't see a compelling real-world case for such a thing.
I thought I'd find it useful while editing, which is what I mainly use Avisynth for, as opposed to processing which most people seem to mainly use it for (see sig for shameless plug).

So I thought the concept could be useful for keeping scripts tidy, and also simplifying the application of some effects like dissolve. With "classic" Avisynth you need to calculate your overlap and trim accordingly, but with superclips you could trim your clips and use the same (super)clips with different lengths of dissolve or even a plain splice (subject to me writing super_dissolve and super_splice functions).

David
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is online now   Reply With Quote
Old 7th February 2014, 01:15   #10  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
No problem, it was kinda my homework too; I didn't feel right about suggesting something without verifying it would actually work. I'm looking forward to seeing what you (and others?) do with it!
raffriff42 is offline   Reply With Quote
Old 7th February 2014, 18:57   #11  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
For your consideration:

Code:
#######################################
### basic splice
function _Splice(val a, val b)
{
    Assert(a.ArrayGet(0)=="BCO-0.2", "_Splice: object mismatch")
    Assert(b.ArrayGet(0)=="BCO-0.2", "_Splice: object mismatch")

    new_object = _CreateClipObject(\
                   a.ArrayGet(1).trim(0,a._prop("firstframe")+a._prop("framecount")-1)++\
                   b.ArrayGet(1).trim(b._prop("firstframe"),0)\
                )\
                .ArraySet(_i("firstframe"), a._prop("firstframe"))\
                .ArraySet(_i("framecount"), a._prop("framecount")+b._prop("framecount"))

    return new_object
}
Obviously anything beyond the trimmed end of a clip a and anything before the trimmed start of clip b is lost, but the two ends of the clip can be _RelativeTrimmed.

Regarding your initial code, personally I thought that storing lastframe instead of framecount would be more intuitive. I think it avoids more of those annoying "-1"s that have to be put into every trim, though I guess there may be just as many times when lastframe would be just as annoying.

I wish that Avisynth had been written with [inclusive start,exclusive end] as parameters to trim - to me it has never made sense that trim(100,200) returns a clip that is 101 frames long.
__________________
My AviSynth filters / I'm the Doctor

Last edited by wonkey_monkey; 7th February 2014 at 18:59.
wonkey_monkey is online now   Reply With Quote
Old 7th February 2014, 23:02   #12  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
Regarding "lastframe," I agree. My (hasty) decision to use framecount was never supposed to be final in any way. Feel free to change things around; just use a new ident, eg "BCO-0.3"

Regarding the utility of it, I'm still not convinced, yet. To re-trim a clip now, it's easy to go back to the parent clip and trim it again. All we are adding here is a way to remember the pre-trimmed state, and that is available already if you have access to the parent clip - and you pretty much always will, unless you are writing a library function. Even then, would you really need access to frames before or after the clip you are working on?

On the other hand, maybe I'm being too short-sighted. These "super clips" (your term is better than "clip objects" - Avisynth clips are objects already) remind me of the things, usually also called clips, you have in a nonlinear editor: you can trim them, un-trim them, apply and remove effects, split them in two, clone them, join them into a sequence, overlay them, etc.
raffriff42 is offline   Reply With Quote
Old 7th February 2014, 23:23   #13  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
Quote:
All we are adding here is a way to remember the pre-trimmed state, and that is available already if you have access to the parent clip
Not quite - you're also adding the ability to extend the already-trimmed state. It may be that you have a clip, and you're happy with it, but somewhere else you might need the same clip but extended by a few frames - even if its just from an script-aesthetic point of view, it seems better to me that you could extend the trimmed clip rather than having to go back to the parent and recut it.

Quote:
Even then, would you really need access to frames before or after the clip you are working on?
Often, if you're editing. Sometimes an audio edit is too harsh, and you need a couple of extra frames, faded, to paste on top of the next clip. Or there's the case of the dissolve.

Still, it's true, super clips probably throw up as many problems as they solve - as a neat concept they'd really have to built-in right at the start, filters written to accommodate them, etc.

Interesting exercise though!
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is online now   Reply With Quote
Old 8th February 2014, 02:14   #14  |  Link
Stereodude
Registered User
 
Join Date: Dec 2002
Location: Region 0
Posts: 1,436
Quote:
Originally Posted by davidhorman View Post
even if its just from an script-aesthetic point of view, it seems better to me that you could extend the trimmed clip rather than having to go back to the parent and recut it.
Because changing trim(26,9199) to trim(26,9199+50) is too hard?
Stereodude is offline   Reply With Quote
Old 8th February 2014, 09:54   #15  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
I'm not talking about just changing one clip's endpoints right at the start of a script.

You could have a need - and yes, these are somewhat artificial examples - to create two clips, both the same length, which are offset from each other by one second. Traditional Avisynth would require:

Code:
a=parent.trim(50,1999)
b=parent.trim(25,1924)
which is inefficient because you're basically repeating yourself, and means the script doesn't fully reflect the intent behind the code, a concept which I think has a name in programming, but which escapes me at the moment.

Instead I could do:

Code:
a=s_parent._trim(50,1999)
b=a._offset(-25)
Which means any script changes to a's trim are automatically reflected in b. When you're editing with a thousand-line Avisynth script, this kind of additional clarity of intention can be helpful (more helpful than using variables, for example).

Another example is one I mentioned earlier, when you have a clip but you need a little extra audio for pasting into another clip to soften the edit. Traditionally:

Code:
clip=parent.trim(123,456)
clip_=parent.trim(457,480) # extra audio
Super clip version:

Code:
clip=s_parent._trim(123,456)
clip_=clip._after(24)
I know the concept is useful to me, anyway.
__________________
My AviSynth filters / I'm the Doctor
wonkey_monkey is online now   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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

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

Forum Jump


All times are GMT +1. The time now is 18:29.


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