My Tool to Detect and Eliminate ALL dropped frames

johnmeyer wrote on 10/29/2009, 2:13 PM
I do a lot of analog video capture and restoration, mostly of VHS tapes. My VCR broke down and since you can't get good new VCRs anymore, I bought a new old stock JVC VS30U. This unit has both DV and VHS/S-VHS capability, timebase corrector, and has the analog to DV encoding built in.

Unfortunately, unless the sun, moon, and all planets are aligned, it drops frames on tapes which are less than pristine. Since this happens internally, I don't get any report from my capture software.

So, since I am stuck for the time being with this pig, I needed to find a way to detect and remove all these drops. Fortunately, as with most conversion hardware, the dropped frame is replaced with an exact duplicate of the previous frame, in order to keep the audio in sync.

I was able to write some software, using AVISynth, which detects the duplicates and then, using motion estimation software, synthesizes the missing frame. It works on interlaced video, and takes advantage of multiple cores, so it is quite fast.

Most important, on VHS and S-VHS quality (i.e., not great quality), the results are visually perfect: I cannot tell the difference between the synthesized frame and the surrounding frames. Just to make the point clear: most frames are not changed, altered, or adjusted in any way; only those which are duplicates are replaced. Thus, even with a lot of dropped frames, 99.9% of the video is un-touched.

Here's the script. As always, this is only for people who already understand and are using AVISynth. As such, I guess I should label this post "OT," but since it is so central to what people do with Vegas, I didn't add that.

#This script finds exact duplicate frames and then interpolates a new frame in place of the duplicate.
#It works on interlaced video.

loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll")

filename = "e:\output_duplicate_frames.txt"

setMTMode(5)
AVISource("e:\frameserver.avi").ConvertToYV12.killaudio()
setMTMode(2,0)

filldropsI(last)

#-------------------
function filldropsI (clip c)
{
even = c.SeparateFields().SelectEven()
super_even=MSuper(even,pel=2)
vfe=manalyse(super_even,truemotion=true,isb=false,delta=1)
vbe=manalyse(super_even,truemotion=true,isb=true,delta=1)
filldrops_e = mflowinter(even,super_even,vbe,vfe,time=50)

odd = c.SeparateFields().SelectOdd()
super_odd=MSuper(odd,pel=2)
vfo=manalyse(super_odd,truemotion=true,isb=false,delta=1)
vbo=manalyse(super_odd,truemotion=true,isb=true,delta=1)
filldrops_o = mflowinter(odd,super_odd,vbo,vfo,time=50)

evenfixed = ConditionalFilter(even, filldrops_e, even, "YDifferenceFromPrevious()", "equals", "0")
oddfixed = ConditionalFilter(odd, filldrops_o, odd, "YDifferenceFromPrevious()", "equals", "0")

Interleave(evenfixed,oddfixed)
Weave()
AssumeFrameBased()
AssumeBFF()
}


Note: If you don't have the multi-core version of AVISynth, delete the two SetMTMode lines. Also, if anyone is interested, I have a more complicated version of this script which also does noise reduction at the same time (using MDegrain2), without too much of an additional time penalty.

Comments

No comments yet - be the first to write a comment...