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. |
10th January 2011, 16:11 | #1 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Completely split into lines
Hi,
This is something I've wanted to do a for along time. I want to split a video in every one of it's lines, and I'm not gonna write 480 crop statements I've used recursion in the past to generate a frequency sweep and found it really slow (though now I can just use lutspa). So I thought of using separatefields a few times. Then I got stuck on how to split by the other prime factors, ie 480=2^5*3*5. I can't just split into 3 sections you understand I need to split up every 3rd line. Luckily in this case the lowest factor is 15 so I could do that individually. Anyhow I came up with a compromise, just pad to nearest pwr2 and split all lines. I find this pretty tough, any ideas? Code:
#Testing splitting video by lines, then motion compensation #576=2^6*3*3 #480=2^5*3*5 #Outline: quadruple height, addborders to the next power of 2 of original height #unweave all the way #motion compensate pair of clips #weave back #you can use conditionalreader to avoid mc extra lines in specific heights #this reminds me of fft butterfly, perhaps you can find lines 480-511 by reversing bits of index (to avoid processing) w=32 h=32 BlankClip(width=w,height=h, pixel_type="YUY2",color_yuv=$40B080) converttoyv12 mt_lutspa(mode="absolute",yexpr="y",uexpr="128",vexpr="128",chroma="process") converttoyuy2 #return last global splith=height nearestpwr2=int(pow(2,int(log(splith)/log(2)+1))) padh=nearestpwr2-splith addborders(0,0,0,padh) unweavestep unweavestep unweavestep unweavestep unweavestep unweavestep function unweave(clip v) { v.assumeframebased.separatefields } function unweavestep(clip v) { v t=splith%2 global splith=t==0?splith/2:splith t==0?unweave:last } Oh ya, could also use a gcd(a,b) and factorn(int n, int index) function Last edited by jmac698; 10th January 2011 at 16:15. |
10th January 2011, 18:39 | #2 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Not sure why you would want to do this, but anyway...Shouldn't that be int(pow(2,ceil(log(splith)/log(2))))?
Otherwise if the height is a power if 2, you will go to the next higher one instead. Also, the number of unweave steps should depend on the exponent, ie ceil(log(splith)/log(2)), not hardcoded at 6. A job for a GScript loop? |
10th January 2011, 22:28 | #5 | Link |
Registered User
Join Date: Dec 2007
Location: Germany
Posts: 632
|
Actually I always wanted to do that too, but in addition I wanted to put the lines back together in a new order for each frame. The result is the original frame but with it's lines swapped all over the place. So for example line 384 gets swapped with line 197, line 412 gets swapped with 59 and so on - "line shuffling".
This is actually just the way pay TV channels were scrambled with "Syster" (in Germany) back in the days. I thought it would be pretty cool to do that, especially if the way the lines get swapped is "predictable" so that it can be completely undone (descrambled so to say). Too bad I don't even know where to start when it comes to rearranging the lines, I mean it could be done with StackVertical(), but... Last edited by TheSkiller; 10th January 2011 at 22:38. |
11th January 2011, 11:13 | #6 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
A single Crop is enough if you put it in the right place. Code:
# Split a clip into strips of 'n' lines. # Individual lines can be obtained by setting n=1, but note n must be even for YV12 # Requires GRunT function SplitLines(clip c, int n) { Assert(c.height%n == 0, "Clip height not a multiple of 'n'") Assert(!(c.IsYV12() && n%2==1), "'n' must be even for YV12 clips") nStrips = c.height/n c = c.ChangeFPS(nStrips*Framerate(c)).AssumeFPS(c) # Repeat each frame 'nStrips' times BlankClip(c, height=n) # template for ScriptClip result GScriptClip("c.Crop(0, (current_frame%nStrips)*n, 0, n)", args="c, nStrips, n") } |
|
11th January 2011, 15:43 | #8 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
ok, here it is:
Code:
# Split a clip into strips of 'n' lines, you can do some processing then, and merge back together # Individual lines can be obtained by setting n=1, but note n must be even for YV12 # Requires GRunT,GScript v=colorbars.trim(0,3) h=v.height splitlines(v,2)#split to lines of height 2 mergelines(h)#merge until height=h function SplitLines(clip c, int n) { Assert(c.height%n == 0, "Clip height not a multiple of 'n'") Assert(!(c.IsYV12() && n%2==1), "'n' must be even for YV12 clips") nStrips = c.height/n c = c.ChangeFPS(nStrips*Framerate(c)).AssumeFPS(c) # Repeat each frame 'nStrips' times BlankClip(c, height=n) # template for ScriptClip result GScriptClip("c.Crop(0, (current_frame%nStrips)*n, 0, n)", args="c, nStrips, n") } function MergeLines(clip c, int h) { l=c.framecount n=h/c.height#n is number of frames to merge, e.g. 480 split to 2line has n=240 GScript(""" for (j=0,l/n-1) { c.trim(j*n,j==0?-1:j*n) for (i=1, n-1) { stackvertical(c.trim(i+j*n,i+j*n)) } b=(j==0)?last:b+last } """) b } It's slow, is there any other ways? |
11th January 2011, 16:16 | #10 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
I found a perfectly fast way to do it already
But I found a strange bug, with version 2. Code:
# Split a clip into strips of 'n' lines, you can do some processing then, and merge back together # Individual lines can be obtained by setting n=1, but note n must be even for YV12 # Requires GRunT,GScript v=colorbars.trim(0,10) h=v.height splitlines(v,2)#split to lines of height 2 mergelines2(h,blankclip(height=480))#merge until height=h, note why do I need blankclip(height=480)? function SplitLines(clip c, int n) { Assert(c.height%n == 0, "Clip height not a multiple of 'n'") Assert(!(c.IsYV12() && n%2==1), "'n' must be even for YV12 clips") nStrips = c.height/n c = c.ChangeFPS(nStrips*Framerate(c)).AssumeFPS(c) # Repeat each frame 'nStrips' times BlankClip(c, height=n) # template for ScriptClip result GScriptClip("c.Crop(0, (current_frame%nStrips)*n, 0, n)", args="c, nStrips, n") } function MergeLines(clip c, int h) { l=c.framecount n=h/c.height#n is number of frames to merge, e.g. 480 split to 2line has n=240 GScript(""" for (j=0,l/n-1) { c.trim(j*n,j==0?-1:j*n) for (i=1, n-1) { stackvertical(c.trim(i+j*n,i+j*n)) } b=(j==0)?last:b+last } """) b } #Note: this version gives a yellow tinge which I can't explain - bug somewhere? Also slow to start and per frame function MergeLines2(clip c, int h, clip template) {#on a guess that stackvertical is too slow l=c.framecount h2=c.height n=h/c.height#n is number of frames to merge, e.g. 480 split to 2line has n=240 template=template.trim(0,-1)#use just 1 frame at a time GScript(""" for (j=0,l/n-1) { template for (i=0, n-1) { overlay(last,c.trim(i+j*n,i+j*n),y=i*h2) } b=(j==0)?last:b+last } """) b } #this version is fast per frame function MergeLines3(clip c, int h, clip template) {#on a guess that stackvertical is too slow l=c.framecount h2=c.height n=h/c.height#n is number of frames to merge, e.g. 480 split to 2line has n=240 template=template.trim(0,-1)#use just 1 frame at a time GScript(""" for (j=0,l/n-1) { template for (i=0, n-1) { layer(last,c.trim(i+j*n,i+j*n).isrgb32?resetmask(c.trim(i+j*n,i+j*n)):c.trim(i+j*n,i+j*n),y=i*h2,level=257) } b=(j==0)?last:b+last } """) b } First, merge2 gives an odd color. Next, merge3 crashes sometimes as I step back and forth through it. Next, why does blankclip get corrupted? Last edited by jmac698; 11th January 2011 at 17:08. |
11th January 2011, 18:18 | #11 | Link | ||
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Quote:
merge3 crashing over repeated stepping could be running out of memory. Try with Task Manager open showing memory usage. You have a bug in merge3 with RGB32 clips (which is probably what is causing your blankclip problem). Layer uses the alpha channel in RGB32 for transparency and ColorBars has a blank (ie transparent) alpha channel, so all the added layers (derived from the original ColorBars) are transparent. At the start of MergeLines3, you need to add c = c.IsRGB32 ? c.ResetMask() : c # ensure RGB32 opaque |
||
12th January 2011, 01:26 | #12 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
After a bit of experimentation, I've tracked down the source of the yellow tinge - it's Overlay.
Since Overlay works internally in YUV, an RGB input clip undergoes a RGB->YUV->RGB conversion. This conversion is not lossless and, according to the documentation, the one done in Overlay is of "slightly worse quality". Since MergeLines2 calls Overlay repeatedly to construct each frame, color degradation builds up, particularly noticeable with initially grey sections. The effect gets stronger with more repetitions, which is why it is most noticable with SplitLines(2) as input. Moral of the story - Overlay is best avoided for RGB, especially if used repeatedly (use Layer instead). Performance and memory use in all the MergeLines functions can be improved by building each frame in parallel, replacing Trim and Splice by SelectEvery(). Here's a revised MergeLines(): Code:
function MergeLines(clip c, int h) { n=h/c.height #n is number of frames to merge, e.g. 480 split to 2line has n=240 c.SelectEvery(n) GScript(""" for (i=1, n-1) { stackvertical(c.SelectEvery(n, i)) } """) } |
12th January 2011, 01:30 | #13 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
I'm getting really inconsistent results. I think once I trigger the bug, everything else is going to act weird and unrepeatable.
Your tip helped, but still the version with overlay uses increasing amounts of memory as you step through each frame. The same code with layer uses the same, small amount of memory. |
12th January 2011, 01:48 | #14 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Great detective work, however I'll call that a bug - overlay should mix in rgb if both inputs are rgb, and I just proved it can be an issue.
Trying to make a simple demo, I ran into another bug: Code:
#crop bug exposebug=false#set to true to crash n=exposebug?241:240 colorbars crop(0,n,0,n) #~ File "pyavs.pyo", line 310, in _GetFrame #~ File "avisynth.pyo", line 139, in BitBlt #~ WindowsError: exception: access violation reading 0x02DDFFE0 |
12th January 2011, 02:25 | #15 | Link | |||
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Quote:
Quote:
Does the right thing for YUV input. |
|||
12th January 2011, 15:05 | #16 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
This is driving me nuts. I tried your version, but I can't say for sure if it's fast, too many weird things going on. I'm getting "Not a clip" which makes no sense:
Code:
v=colorbars.trim(0,10) h=v.height splitlines(v,2)#split to lines of height 2 MergeLines(v,h)#merge until height=h, note why do I need blankclip(height=480)? function SplitLines(clip c, int n) { Assert(c.height%n == 0, "Clip height not a multiple of 'n'") Assert(!(c.IsYV12() && n%2==1), "'n' must be even for YV12 clips") nStrips = c.height/n c = c.ChangeFPS(nStrips*Framerate(c)).AssumeFPS(c) # Repeat each frame 'nStrips' times BlankClip(c, height=n) # template for ScriptClip result GScriptClip("c.Crop(0, (current_frame%nStrips)*n, 0, n)", args="c, nStrips, n") } function MergeLines(clip c, int h) { n=h/c.height #n is number of frames to merge, e.g. 480 split to 2line has n=240 c.SelectEvery(n) GScript(""" for (i=1, n-1) { stackvertical(c.SelectEvery(n, i)) } """) } Code:
temp=last """) temp } Code:
#Requires gscript v=colorbars(height=2).trim(0,240*20-1) h=v.height MergeLines(v,480) function MergeLines(clip c, int h) {#as suggested by Gavino about 4 frames/sec, 449mb memory n=h/c.height #n is number of frames to merge, e.g. 480 split to 2line has n=240 c.SelectEvery(n) GScript(""" for (i=1, n-1) { stackvertical(c.SelectEvery(n, i)) } """) } |
12th January 2011, 15:22 | #17 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Result is that n=1 inside the function, so the loop range is empty and so GScript (and hence the function) returns a 'void' result. |
|
12th January 2011, 16:06 | #19 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
I did it! I could swear I'm looking at a VHS SLP recording, amazing...
Code:
#VCR line jitter simulator ver. 0.1 by jmac698 #requires both gscript and grunt colorbars(pixel_type="YUY2").trim(0,10) pointresize(width,height*4)#get line resolution by working around min height 4 limitations h=height splitlines(4)#split to lines of height 2 - note the jitter function requires height>=4 jitter #return last MergeLines(h)#merge until height=h, note why do I need blankclip(height=480)? blur(1).blur(1).blur(1) pointresize(width,height/4) temp=last u=temp.utoy v=temp.vtoy u=u.bilinearresize(30,height).bilinearresize(320,height)#it's actually better than this, placement of transitions is finer v=v.bilinearresize(30,height).bilinearresize(320,height) ytouv(u,v,temp) function SplitLines(clip c, int n) { Assert(c.height%n == 0, "Clip height not a multiple of 'n'") Assert(!(c.IsYV12() && n%2==1), "'n' must be even for YV12 clips") nStrips = c.height/n c = c.ChangeFPS(nStrips*Framerate(c)).AssumeFPS(c) # Repeat each frame 'nStrips' times BlankClip(c, height=n) # template for ScriptClip result GScriptClip("c.Crop(0, (current_frame%nStrips)*n, 0, n)", args="c, nStrips, n") } function MergeLines(clip c, int h) { n=h/c.height #n is number of frames to merge, e.g. 480 split to 2line has n=240 c.SelectEvery(n) GScript(""" for (i=1, n-1) { stackvertical(c.SelectEvery(n, i)) } """) } function shift(clip v, int sx, int sy) { v#shift a video sx, sy pixels, sx<0 is left, sy<0 is down pointresize(width*2,height*2)#to allow 1 pixel shifts in YV12 sx=sx*2 sy=sy*2 l=(sx<0)?-sx:0 r=(sx<0)?0:sx t=(sy<0)?0:sy b=(sy<0)?-sy:0 crop(l,t,-r,-b) addborders(r,b,l,t) bilinearresize(v.width,v.height) } function jitter(clip v) {#note: a good tape could typically be +-3 without a TBC, distribution is not realistic ScriptClip(v,""" shift(rand(6)+4,0) """) } |
12th January 2011, 19:49 | #20 | Link | |
Moderator
Join Date: Nov 2001
Location: Netherlands
Posts: 6,364
|
Quote:
|
|
Thread Tools | Search this Thread |
Display Modes | |
|
|