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. |
|
|
Thread Tools | Search this Thread | Display Modes |
2nd February 2014, 19:32 | #1 | Link |
Formerly davidh*****
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) Code:
s_clip.supertrim(50,150) return s_clip.video Code:
s_clip.untrim() # restore full length clip s_clip.extend(50) # add another fifty frames to the end from the original clip 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 |
4th February 2014, 21:33 | #3 | Link | ||
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,493
|
Quote:
Quote:
|
||
5th February 2014, 00:22 | #4 | Link |
Retried Guesser
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... |
5th February 2014, 14:45 | #6 | Link |
Retried Guesser
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. |
6th February 2014, 05:57 | #8 | Link |
Retried Guesser
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 Last edited by raffriff42; 7th February 2014 at 01:18. Reason: version 0.2.0 |
7th February 2014, 00:01 | #9 | Link | |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,493
|
Wow, thanks raffriff, I wasn't expecting to anyone to do my homework for me!
Quote:
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 |
|
7th February 2014, 18:57 | #11 | Link |
Formerly davidh*****
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 } 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. Last edited by wonkey_monkey; 7th February 2014 at 18:59. |
7th February 2014, 23:02 | #12 | Link |
Retried Guesser
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. |
7th February 2014, 23:23 | #13 | Link | ||
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,493
|
Quote:
Quote:
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! |
||
8th February 2014, 09:54 | #15 | Link |
Formerly davidh*****
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) Instead I could do: Code:
a=s_parent._trim(50,1999) b=a._offset(-25) 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 Code:
clip=s_parent._trim(123,456) clip_=clip._after(24) |
Thread Tools | Search this Thread |
Display Modes | |
|
|