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 10th January 2011, 16:11   #1  |  Link
jmac698
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
}
So I need to process separately on the (equivalent of) each pair of video lines from two clips eventually.
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.
jmac698 is offline   Reply With Quote
Old 10th January 2011, 18:39   #2  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Not sure why you would want to do this, but anyway...
Quote:
Originally Posted by jmac698 View Post
Code:
nearestpwr2=int(pow(2,int(log(splith)/log(2)+1)))
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?
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 10th January 2011, 21:25   #3  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
unweave steps uses splith to determine if unweave should be applied. It is called 6 times manually to avoid recursion.
jmac698 is offline   Reply With Quote
Old 10th January 2011, 22:20   #4  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Yes, I know, but that puts an arbitrary upper limit on the number of splits.
Seems a natural candidate for a GScript 'for' or 'while' loop.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 10th January 2011, 22:28   #5  |  Link
TheSkiller
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.
TheSkiller is offline   Reply With Quote
Old 11th January 2011, 11:13   #6  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by jmac698 View Post
I want to split a video in every one of it's lines, and I'm not gonna write 480 crop statements
Actually, it's very simple.
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")
}
It could also be done without GRunT (ie with the standard ScriptClip) by using global variables, but that stops the function being used more than once in a script.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 11th January 2011, 13:47   #7  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
That's awesome, thanks!
Now put it back together again
jmac698 is offline   Reply With Quote
Old 11th January 2011, 15:43   #8  |  Link
jmac698
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
}
Is it gonna run out of memory or anything?
It's slow, is there any other ways?
jmac698 is offline   Reply With Quote
Old 11th January 2011, 15:56   #9  |  Link
hanfrunz
Registered User
 
hanfrunz's Avatar
 
Join Date: Feb 2002
Location: Germany
Posts: 540
mmmh i think this whole task should be done inside a filter. That would be a lot faster. I do not have the time to do it right now, maybe somebody is quicker than me

hanfrunz
hanfrunz is offline   Reply With Quote
Old 11th January 2011, 16:16   #10  |  Link
jmac698
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
}
I'm having some very odd bugs here. G, I think your plugins are buggy
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.
jmac698 is offline   Reply With Quote
Old 11th January 2011, 18:18   #11  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by jmac698 View Post
I'm having some very odd bugs here. G, I think your plugins are buggy
It's always a possibility, but I really don't think so in this case.
Quote:
First, merge2 gives an odd color. Next, merge3 crashes sometimes as I step back and forth through it. Next, why does blankclip get corrupted?
I think the odd color is probably due to a bug in Overlay. I need to investigate more, but it only seems to affect RGB and with SplitLines(n) where n<=8.

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
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 12th January 2011, 01:26   #12  |  Link
Gavino
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))
    }
  """)
}
The same change could be made to the Overlay and Layer variants, but I think using StackVertical should be more efficient and works for all colorspaces.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 12th January 2011, 01:30   #13  |  Link
jmac698
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.
jmac698 is offline   Reply With Quote
Old 12th January 2011, 01:48   #14  |  Link
jmac698
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
jmac698 is offline   Reply With Quote
Old 12th January 2011, 02:25   #15  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by jmac698 View Post
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.
Overlay is a known memory hog, so I think the StackVertical version should be best for overall performance.
Quote:
Originally Posted by jmac698 View Post
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.
Not really a bug, more a limitation, since it was designed to work that way. If there is a bug, it is that the RGB<->YUV conversion is sub-optimal.
Quote:
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)
Yes, it should give an error instead of crashing.
Does the right thing for YUV input.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 12th January 2011, 15:05   #16  |  Link
jmac698
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))
    }
    
  """)
  
}
I have to add this to get it to work:
Code:
    temp=last
  """)
   temp
}
yet this works fine:
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))
    }
""")
}
Does it happen for you too?
jmac698 is offline   Reply With Quote
Old 12th January 2011, 15:22   #17  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by jmac698 View Post
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)
...
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))
    }    
  """)  
}
It should just be MergeLines(h), as v is still the original clip.
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.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 12th January 2011, 15:26   #18  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
oh, thank goodness! I'm glad your still online, I really wanted to do some actual video processing with this today.
jmac698 is offline   Reply With Quote
Old 12th January 2011, 16:06   #19  |  Link
jmac698
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)
  """)
}
jmac698 is offline   Reply With Quote
Old 12th January 2011, 19:49   #20  |  Link
Wilbert
Moderator
 
Join Date: Nov 2001
Location: Netherlands
Posts: 6,364
Quote:
This conversion is not lossless and, according to the documentation, the one done in Overlay is of "slightly worse quality".
What do you mean by "slightly worse quality"? Less accurate/precision?
Wilbert is offline   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 23:42.


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