Log in

View Full Version : Need help fixing a bad capture pattern


zambelli
24th December 2006, 06:30
I have an AVI that was captured from an analog VHS source. The capture wasn't perfect and some frames ended up getting dropped in a strange pattern. I don't have access to the hardware or the original VHS source so I can't do a re-capture - I need to work with what I've got.

On occasion (no more than once every minute or so) the capture card dropped a video frame - but instead of simply skipping the dropped frame, it made up for it by duplicating an old frame - but not the last one. If we assume the frame order should've been:

0 1 2 3 4 5 6 7 8 9

and the card dropped frame #6, the actual capture video frame order ended up being:

0 1 2 3 4 3 5 7 8 9


I'm looking for a way to detect these occurences and correct them. Any idea is welcome. If this is a common issue and a plugin exists - perfect. If somebody has a script idea, that's great too. Hopefully a bad sequence like the one above could be corrected into something like:

0 1 2 3 4 5 5/7 7 8 9

where 5/7 is a 50%-50% blend between frames #5 and #7. It'd certainly look better than the jerky sequence that I currently have.

Guest
24th December 2006, 14:31
One option for the blending solution is Decimate(mode=1). Decimate is in the Decomb package. Read the Decomb reference manual to learn how to set the threshold for proper duplicate detection, etc.

I believe TDecimate() can also do it.

but instead of simply skipping the dropped frame, it made up for it by duplicating an old frame It has to do that, otherwise audio sync would be lost.

MOmonster
24th December 2006, 15:19
But decimate will output:
0 1 2 3 4 4/5 5 7 8 9
or ?
So this is not the optimal solution for this problem.

@zambelli
is the source interlaced?
(0 1 1 2 4 5 -> after bobbing: 0t 1b 2t 3b 2t 3b 4t 5b 8t 9b 10t 11b)
If yes, how you wnat the output to be? Deinterlaced with introduced single blends for smoother motion or interlaced with doubleblending?

Guest
24th December 2006, 15:28
Yeah, you're right. I only skimmed the problem description. :)

@zambelli

Can you upload an unprocessed sample clip?

Didée
24th December 2006, 16:28
The framework of this function (http://forum.doom9.org/showthread.php?p=879309#post879309) should be usable. For interlaced content directly, for progressive content the internal bobbing would need to be pulled out.
Needed modification is that the created mask would have to be delayed by 4 fields / by 2 Frames, since in zambelli's case the dup frame is two frames ahead of the missing frame.

zambelli
25th December 2006, 03:36
is the source interlaced?
Yes, it is. Whenever a frame is dropped, it is a full frame that includes both fields. Parity never changes.
Can you upload an unprocessed sample clip?
Sure. http://www.citizeninsomniac.com/video/framedropsample.avi. It's HFYU encoded.
Check out frames 3-7 and 57-61 for examples. Pay attention to the people who are moving.

IanB
26th December 2006, 14:46
Okay frame 5 is an exact dup of frame 3 and frame 59 is an exact dup of frame 57. There seems to be a whole frame missing between frames 6 and 7. However frames 60 and 61 seem correctly contiguous. :confused: The FPS=1000000/33367= 29.96973 which is just a tad slow, this may be an indication of lost frames or a very slack version of 29.97!

Yes this seems to be a real crappy dropped frame implementation where the missing frame is replaced not by the previous frame but by the second previous frame. Best guess the capture app is exactly double buffered and just reuses the existing buffer for a drop, hence the 2nd previous, yuck! and sometimes it misses the drop entirely, or maybe when it doesn't notice the drop you get the 2nd prev dup.

As a start try this script.AviSource("framedropsample.avi")
BlankClip(Last, 1) + Last # Add an edge frame

A=ConvertToYV12()
B=A.DuplicateFrame(0).DuplicateFrame(0)

# DeleteFrame(0).ShowFrameNumber(True).DuplicateFrame(0)

# Make a cheap filler frame - Use MV stuff for high quality
Replacement=Merge(DuplicateFrame(0), DeleteFrame(0))

ConditionalFilter(Replacement, Last, "LumaDifference(A, B)", "<", "0.00001")

Trim(1, 0) # Remove edge frameGetting rid of the out of order frames helps a lot. You need to analyze a longer stream to see if the pattern holds generally.

Possible a 2 pass approach might be needed, using WriteFile/LumaDifference then ReadFile/ConditionalFilter with some hand tweaking of the intermediate file.

Depending on how much effort you want to commit you could use MVTools to rebuild the missing frames.

MOmonster
26th December 2006, 15:29
Have you tried Didee`s function?
You can also test this (http://forum.doom9.org/showthread.php?p=857487#post857487):
a = source
b = source.selectevery(2,1,0)

repair_ff(a,b)
#deinterlace+decimate(mode=1)
Canīt test how good this work or not work, but itīs worth a try.
Canīt write a small specified function for your problem because I have no avisynth the next two weeks.

zambelli
27th December 2006, 03:18
As a start try this script.
Thank you, Ian! This is a great starting point. There seem to be some cases where the captured sequence is "0 1 2 3 4 3 6 7", and then there are some where it's "0 1 2 3 4 3 5 7". Your solution works for the former. I've managed to get a script working for the latter too, but I'm not sure if it's possible to have a script that dynamically fixes both cases.

Depending on how much effort you want to commit you could use MVTools to rebuild the missing frames.
I'm OK with a simple Merge. The most important thing is the fluidity of motion. A mediocre blend is far less noticeable than an out-of-order frame.

IanB
28th December 2006, 13:48
As the material is interlaced you should intelligent bob the fields in the area under repair and insert appropriate replacement blended fields rather than whole frames. Motion in the right direction but at slightly the wrong time is forgiveable, motion in the wrong direction is obvious and bad (hence this thread).

i.e. "0 1 2 3 4 3 6 7" after repair could become
"... 3b 3t 4b 4t W X 6b 6t 7b 7t" where
W = n5b = (2*Bob(4t)+6b)/3
X = n5t = (4t+2*Bob(6b))/3

and "0 1 2 3 4 3 5 7" after repair could become
"... 3b 3t 4b 4t 5b 5t Y Z 7b 7t" where
Y = n6b = (2*Bob(5t)+7b)/3
Z = n6t = (5t+2*Bob(7b))/3

Now if you cannot separately identify the 2 cases a compromise solution might be to shift the 5/6 frame up 1 field and interpolate a field on either side. i.e.
"... 3b 3t 4b 4t W X Y Z 7b 7t" where
W = n5b = (Bob(4t)+56b)/2
X = n5t = Bob(56b)
Y = n6b = Bob(56t)
Z = n6t = (56t+Bob(7b))/2

Thoughts?