Log in

View Full Version : mv bob and very lost first time user


wildgrace
14th April 2006, 17:33
I am about to use mvbob, avisynth and virtualdubmpeg for the first time.

I've read the tututorials and I'm still lost.

Can someone give me a step-by-step. And I mean mini step by mini step.

I tried looking for a video tuturial or a book on the subject, but I could not find anything. I've looked through the forums, but I haven't found what I need. (I taught myself HTML code from a book, I should be able to figure this out.)

I want to convert 60i to 24p. (Side question once converted to 24p does mvbob put in the flag for the 2:3 pulldown?)

I've dowloaded avisynth and unzipped to it's own folder. I've downloaded virtualdubpeg to it's own folder. And downloaded an unzipped mvbob (avs file format) to its own folder and them moved the files into the plugin section of virtualdubmob.

I'm using dv/hdv footage.

Any help for the tech dummy in Canada who can't seem to figure this out is much appreciated. I admit to being totally lost here.

Below is the code
#Helper functions:

#revert PAL-DV to YV12 for quality reasons; needs yuy2 input (ie. canopus-dv-decoder)
function reYV12(clip i)
{

yx = i.converttoyv12().greyscale()
x = i.separatefields().assumeframebased().separatefields().selectevery(4, 0, 2).weave()
ux = x.utoy().converttoyv12()
vx = x.vtoy().converttoyv12()
ytouv(ux, vx, yx)
}


#wrapping bob() ....
function dumbbob(clip i, int "height")
{
i.bob(0, 1, height = height)
getparity(i) ? assumetff() : assumebff()
}

#fast ELA-bob, se=0 by default => dumb bob
function tomsbob(clip i, int "se")
{
se = default(se, 0)
interleave(i.tomsmocomp(-1, 0, 0),i.doubleweave().selectodd().tomsmocomp(-1, 0, 0))
assumeframebased()
getparity(i) ? assumetff() : assumebff()
}

#fast kernel bob, th=0 by default => dumb bob
function krnlbob(clip i, int "th")
{
th = default(th, 0)
i.leakkernelbob(order = (getparity(i) ? 1 : 0), threshold = th)
assumeframebased()
getparity(i) ? assumetff() : assumebff()
}

#slow, but accurate EEDI-bob, always dumb ;)
function eedibob(clip i)
{
getparity(i) ? i.separatefields().eedi2(field = 3) : i.separatefields().eedi2(field = 2)
assumeframebased()
getparity(i) ? assumetff() : assumebff()
}

#cut down progressive to interlaced
function reinterlace(clip i, bool "enableyv12output")
{
enableyv12output = default(enableyv12output,false)
i = (isyv12(i) && enableyv12output) ? i : i.converttoyuy2()
i.separatefields().selectevery(4, 0, 3).weave()
}

#Deinterlacer that avoids residual cobing with tricky motion at all cost.
# with bobbing-overweights-weaving-technology-tm
function securedeint(clip i, int "th", int "l", int "type")
{
function staticmask(clip e, int th, int l)
{
e0 = e.motionmask(thy1 = 0, thy2 = th, thc1 = 0, thc2 = round(th / 1.5), thSD = 255, u = 3, v = 3)
#\.temporalsoften(6, 1, 1)
e1 = e0.trim(1, 0)
e2 = e0.trim(2, 0)
e3 = e0.trim(3, 0)
e4 = e0.trim(4, 0)
e5 = e0.trim(5, 0)
e6 = e0.trim(6, 0)
e7 = e0.trim(7, 0)

ea0 = logic(e0, e1, "OR", u = 3, v = 3)
ea1 = logic(e2, e3, "OR", u = 3, v = 3)
ea2 = logic(e4, e5, "OR", u = 3, v = 3)
ea3 = logic(e6, e7, "OR", u = 3, v = 3)

eb0 = logic(ea0, ea1, "OR", u = 3, v = 3)
eb1 = logic(ea2, ea3, "OR", u = 3, v = 3)

ec = logic(eb0, eb1, "OR", u = 3, v = 3)

(l==0) ? ec .duplicateframe(0).duplicateframe(0).duplicateframe(0) :\
(l==1) ? eb0.duplicateframe(0) :\
(l==2) ? ea0 : e0
}

th = default(th, 6)
l = default(l, 1)
type = default(type, 3)

i.converttoyv12(interlaced = true).separatefields()
e = selecteven().staticmask(th, l)
o = selectodd() .staticmask(th, l)
m = interleave(e, o).undot().dumbbob()
m = merge(m.trim(1, 0), m, 0.5).binarize(u = 3,v = 3)

b = (type==0) ? i.dumbbob() : (type==1) ? i.tomsbob() : (type==2) ? i.krnlbob() : i.eedibob()
d=i.doubleweave()

isyv12(i) ? maskedmerge(b, d, m, u = 3, v = 3) : overlay(b, d, mask = m.converttoyuy2(), greymask = false)

assumeframebased()
getparity(i) ? assumetff() : assumebff()
}

function mvconv(clip i, int "num", int "den", int "blk")
{
blk = default(blk, 8)
blk = (blk==8) ? 8 : 4

tm=true
#lm=10000

rate= (defined(num) && defined (den)) ? -1 : framerate(i)
i = isYV12(i) ? i : i.convertttoyv12()

backward_vec = i.MVAnalyse(isb = true, blksize=blk, truemotion=tm, pel=2, idx=4)
forward_vec = i.MVAnalyse(isb = false, blksize=blk, truemotion=tm, pel=2, idx=4)
cropped = (blk==8) ? i.crop(4,4,-4,-4) : i.crop(2,2,-6,-6)
# by half of block size 8
backward_vec2 = cropped.MVAnalyse(isb = true, blksize=blk, truemotion=tm, pel=2, idx=3)
forward_vec2 = cropped.MVAnalyse(isb = false, blksize=blk, truemotion=tm, pel=2, idx=3)


o = (rate==50) ? i.MVFlowFps2(backward_vec,forward_vec,backward_vec2,forward_vec2,num=60000, den=1001,idx=4,idx2=3) : \
((rate>59.9) && (rate<60.01)) ? i.MVFlowFps2(backward_vec,forward_vec,backward_vec2,forward_vec2,num=50,idx=4,idx2=3) : \
i.MVFlowFps2(backward_vec,forward_vec,backward_vec2,forward_vec2,num=num,den=den,idx=4,idx2=3)

return o
}


function MVbob(clip c,int "blksize", int "pel", int "th", int "ths", int "bobth", bool "quick")
{
#internal helper function to find static areas (experimental)
function static_o_matic(clip i, clip j, int thy, int thc)
{
a = isyv12(i) ? i.motionmask(thy1=0,thy2=thy,thc1=0,thc2=thc,thSD=255,y=3,u=3,v=3) \
: i.converttoyv12().motionmask(thy1=0,thy2=thy,thc1=0,thc2=thc,thSD=255,y=3,u=3,v=3)
# a=i.converttoyv12().motionmask(thy1=0,thy2=thy,thc1=0,thc2=thc,thSD=255,y=3,u=3,v=3)
logic(a,a.trim(1,0),"OR",y=3,u=3,v=3)
RemoveGrain(1) # undot()
overlay (i,j, mask=last)
#MaskedMerge(i,j,last,U=3,V=3) #
}

#disable all scene detection of mvcompensate(), because mvbob() is self-correcting due to the corrector()
sc=255

# threshold for correcting failed compensated motion
th=default(th,8)

# threshold for correcting static areas
ths=default(ths,3)

# deinterlacing threshold for the motion vector analysis do not go much higher than 10
bobth=default(bobth,6)

#denoise the video for the bobber (better static areas for noisy video, crappy)
quick=default(quick,false)

#defaults for the mocomp
blksize=default(blksize,8)
scd=(blksize==8)? 300 : round(300/4)
pel=default(pel,2)


#determine clip Fieldorder
order=(c.getparity==true)? 1:0
yv12 = isyv12(c)

# bobx -> kerneldeinterlaced video, used for motion search

# mvf -> motion vectors forward
# mvb -> motion vectors backward

# bobd -> blurred bobx for error checking (correcting false compensated blocks!)
# bobdf -> forward compensated bobd
# bobdb -> backward compensated bobd

# fields-> ELA-deinterlaced fields for motion compensated output and compensation correction
# mcf -> forward compensated fields
# mcb -> backward compensated fields
# cv -> average of mcb and mcf

# dpf -> forward compensated fields (global motion)
# dpb -> backward compensated fields (global motion)
# dp -> average of dpb and dpf

# mc -> corrected motion compensated result

# create clip for motion analysis and hole-filling
bobc = quick ? c.securedeint(th=bobth, type=1) : c.securedeint(th=bobth, type=3)
bobd = yv12 ? bobc : bobc.converttoyv12()
bobd = bobd.removegrain(11)


# create clip for motion compensation
fields = bobc
fields= yv12 ? fields : fields.converttoyv12()

# create motion vectors
mvf=bobd.mvanalyse(blksize=blksize,pel=pel,isb=false,chroma=true,idx=1,truemotion=true)
mvb=bobd.mvanalyse(blksize=blksize,pel=pel,isb=true, chroma=true,idx=1,truemotion=true)

# create clips for mismatch detection
bobdf=bobd.mvflow(mvf,idx=1).removegrain(11).removegrain(11)
bobdb=bobd.mvflow(mvb,idx=1).removegrain(11).removegrain(11)
bobdc=bobd.removegrain(11).removegrain(11)

# create the motion compensated clip that are passed through to the output
mcf=fields.mvflow(mvf,idx=2)
mcb=fields.mvflow(mvb,idx=2)
cv=merge(mcf,mcb,0.5)

# detect mismatches of mvtools and replace them with motion adaptive bobbed areas
mc=corrector(bobdc,fields, bobdf,bobdb, mcf,mcb, mode=0,th=th)

# merge corrected output and raw output into one frame horizontally
mc = quick ? mc : stackhorizontal(mc,cv)

# select the correct lines
compensated_even= mc.selecteven().separatefields().selectodd()
compensated_odd = mc.selectodd() .separatefields().selecteven()

# ensure correct chroma format
compensated_even=yv12 ? compensated_even : compensated_even.converttoyuy2()
compensated_odd =yv12 ? compensated_odd : compensated_odd .converttoyuy2()

# merge them with the original fields
original_even=c.separatefields().selecteven()
original_odd =c.separatefields().selectodd()

even = quick ? interleave(original_even, compensated_even).weave() : interleave(stackhorizontal(original_even, original_even), compensated_even).weave()
odd = quick ? interleave(original_odd , compensated_odd ).weave() : interleave(stackhorizontal(original_odd , original_odd ), compensated_odd ).weave()


interleave(even,odd)

#separate into corrected and raw video || correct static areas
mc_corr = quick ? last : crop(last,0,0,width/2,0)
mc_raw = quick ? last : crop(last,width/2,0,0,0)
quick ? last : static_o_matic(mc_raw,mc_corr,ths,ths)
(order==1) ? last.assumetff() : last.assumebff()

}


# needed plugins
LoadPlugin("RemoveGrain_v10pre1.dll")
loadplugin("masktools.dll")
loadplugin("mvtools.dll")
loadplugin("tomsmocomp.dll")
loadplugin("leakkerneldeint.dll")
loadplugin("eedi2.dll")
loadplugin("undot.dll")

actionman133
18th April 2006, 02:17
MVBob () won't convert your framerate like you ask. It deinterlaces your source video, and double the output framerate. If you input 30 interlaced frames, it outputs 60 progressive frames. What you'll need to use is MVConv (), which, luckily for you, is in the code you posted.

Create an avs script file where your video is (just create a new text document and change 'txt' to 'avs'), and move all the contents of the MVBob package to the AVISynth plugins folder.

Open the avs file in notepad and write the following:

c = AVISource ("filename.avi") # Open the video
deint = c.MVBob (4, 2) # Deinterlace to 60p
num = int (deint.Framerate () * 400)
den = 1000
film = deint.MVConv (num, den, 4) # Convert to 24p
return film

If you receive an error about AVISource when you open the script in VirtualDub, then replace it with DirectShowSource ("filename.avi")

This will return 23.976p/24p output to VirtualDub, depending on whether your original source was 29.97 or 30 fps, respectively. And it won't apply pulldown flags. I believe that job is left the encoding application, but if you want to hardcode the pulldown (not recommended, but it can be done), then use this code instead.

c = AVISource ("filename.avi") # Open the video
deint = c.MVBob (4, 2) # Deinterlace to 60p
num = int (deint.Framerate () * 400)
den = 1000
film = deint.MVConv (num, den, 4) # Convert to 24p
pulldown = film.AssumeTFF ().SeparateFields ().\
SelectEvery (8, 0,1, 2,3,2, 5,4, 7,6,7).Weave () # Apply 3:2 pulldown
Return Pulldown

I don't understand why you would use pulldown like this though, as doing so is only necessary if you're outputting to an interlaced source, which it was to begin with. Unless you want to recreate the 'film look' with video material, then I would not recommend the pulldown.

[EDIT]: forgot to make num an integer

wildgrace
19th April 2006, 00:00
thank you, Thank You, THANK YOU.

actionman133
19th April 2006, 02:44
Lol. Okay get up off your knees, your embarrassing me... :D

But still, glad to help. If I may provide a warning, MVConv () may actually mess up some of your frames if there is a large amount of motion, say a quick camera pan. I recommend you do a draft encode on your source to determine if you have this problem...

If you'd like an example, I have a small test clip under the name 'MVConv Errors' available for download on my website that shows you what this corruption can look like. Even in this complex clip, there are only a few buggy frames, but it ruins the shot. It would be a good idea to check this before you commit to a full encode...

http://actionman133.isa-geek.net:8080/preview/preview.html