Log in

View Full Version : just for fun: a scripted IVTC + decimator


Mug Funky
1st October 2005, 04:03
hey all.

as some of you might know, i'm continually trying to figure out how to get a perfect hybrid NTSC to PAL conversion going in avisynth. i also tend to go all "head a splode" whenever i try to sit down and figure it out.

well, as a start, i've written an IVTC function using only masktools and avs internal functions.

because of how i plan to treat interlaced NTSC in future, this function outputs doubled frame rate (47.952 fps), but hasn't mismatched a field yet on the 1 clip i tested it on.

it's pretty slow, as it checks for the ideal decimation pattern per frame rather than per cycle, or ideally whenever a pattern break is encountered. i'm sure someone with a less linear brain could make this a whole lot faster :) (scharfi or didee come to mind... i'm too lazy at the moment, but once my current project-from-hell is over with i'll have some more thinking time).

here's the very-messy-but-works-as-proof-of-concept script:
function blindmatch (clip c,float "thresh")
{
global thresh=default(thresh,0.00001)
c=c.doubleweave()
global c = c
d=c.horizontalreduceby2()
global swapped = c.doubleweave().selectodd()
global cmetric = d.yv12convolution(horizontal="1",vertical="-1 2 -1")
global smetric = d.doubleweave().selectodd().yv12convolution(horizontal="1",vertical="-1 2 -1")

global e= scriptclip(c,"cmetric.averageluma > smetric.averageluma? swapped : c")

global metric4 = yv12lutxy(e.selectevery(5,2,2,2,2),e.selectevery(5,4,4,4,4),yexpr="x y - abs")
global metric3 = yv12lutxy(e.selectevery(5,1,1,1,1),e.selectevery(5,3,3,3,3),yexpr="x y - abs")
global metric2 = yv12lutxy(e.selectevery(5,0,0,0,0),e.selectevery(5,2,2,2,2),yexpr="x y - abs")
global metric1 = yv12lutxy(e.selectevery(5,4,4,4,4),e.selectevery(5,1,1,1,1),yexpr="x y - abs")
global metric0 = yv12lutxy(e.selectevery(5,3,3,3,3),e.selectevery(5,0,0,0,0),yexpr="x y - abs")

scriptclip(e.selectevery(5,0,1,2,4),"metric4.averageluma() < thresh ? e.selectevery(5,0,1,2,3)" +
\" : metric3.averageluma() < thresh ? e.selectevery(5,0,1,2,4)" +
\" : metric2.averageluma() < thresh ? e.selectevery(5,0,1,3,4)" +
\" : metric1.averageluma() < thresh ? e.selectevery(5,0,2,3,4)" +
\" : e.selectevery(5,1,2,3,4)")

}

hope someone finds a use for it.

defaults will be fine for anything you care to test it on - it's only meant for pure film 3:2 stuff for now, as the metrics don't work without one and i imagine it'll throw an error on interlaced or field-blended video (as no pair of fields will be under the threshold).

to use it as a regular (but very slow and no better than telecide) IVTC+decimate, just whack a selecteven after it.

[edit]
oh, that's a surprise - it doesn't crash on pure interlaced material... looking back it makes sense. it'll just return combs :)

mg262
2nd October 2005, 17:31
This looks like fun (though essentially all my material is PAL, so I have no useful feedback). But I wanted to say that because there is a processor primitive to compute Sum-Absolute-Difference, the second half of your script could be sped up considerably with a (relatively easy to write) custom filter -- something to keep in mind when you build more complex scripts.

I will be particularly interested to see what you do with hybrid material -- not so much the how, but rather what a good PAL conversion of hybrid material even looks like.

Mug Funky
3rd October 2005, 05:39
hehe... i can think of many ways to speed up the decimator part, possibly without the need to write a custom filter (like choosing a decimation cycle and only checking the other cycles if the current one slips over the threshold... that would speed it up several times).

my idea of a good hybrid to pal conversion is to speed up the film bits, and blend/motion-compensate the rest. for stuff that's mostly film, it's actually _nearly_ enough to just deinterlace the combed output of the current script. i've made a mod of this one that uses tdeint before the decimator (but after the matching) and it looks okay, but a bit jerky for my liking. also, while it correctly finds the film parts, it tends to phase-shift (2:2 pulldown) them half the time. this looks fine on a TV, but obviously isn't optimal, and running a field-matcher afterward to fix it seems like a massive copout to me :)

basically my goal is to create a standards-conversion script that's robust enough to be run with defaults on all material, but without giving all material the same treatment - i'd like to detect the type of video rather than having to look at the video... mainly so people without avisynth experience can make good encodes straight away from any NTSC source (PAL would be passed through as is, naturally). although that could mean scripting myself out of a job...