Log in

View Full Version : Why does this script work?


il Canoista
11th January 2007, 00:34
The source is an AVI with interlaced mjpeg video and wave audio, captured from a VHS source. I tried to encode this file to mpeg2 to make a DVD, but the resulting video was really unstable: I think that there was some error in the field order. The error was quite uncommon because I wasn't able to solve it inverting the fields. The only way to acquire a correct results was using this script:

clip = SegmentedDirectShowSource ("D:\Acquisizioni\conferenza.avi")
clip = separatefields (clip)
a = trim (clip, 0, 0)
b = trim (clip, 3, 0) # <= That number 3 is quite unusual...
a = selecteven (a)
b = selecteven (b)
a = peachsmoother (a)
b = peachsmoother (b)
a = Lanczos4Resize(a, 704,288)
b = Lanczos4Resize(b, 704,288)
a = crop (a,0,1,0,0) # <= using this to raise the field of 1 line
a = addborders (a,0,0,0,1) <= using this to raise the field of 1 line
interleave (a,b)
weave
Trim(0,103553)
fadein (25)
converttoyv12
saturation = 1.2
contrast = 1
cv = - (1 - saturation) * 256
cy = - (1-contrast) * 256
ColorYUV(off_y=5, gain_y=-15, cont_u = cv, cont_v = cv, cont_y = cy, opt="coring", analyze = true)
crop (8,0,-8,-16)
addborders (8,0,8,16)
normalize
I put a comment beside the instructions that solved the problem. Note that peachsmoother is a spatio-temporal smoother.
The output was as stable as the one obtained discarding one field, but it looks better.
The question is why this script works... What's the problem with the source file?
And last but not least: are there errors?

Didée
11th January 2007, 03:33
What's the problem with the source file?
Nothing, probably.


are there errors?
Only one: your script as a whole. :D ;)


The source probably is TFF. But AVI doesn't carry fieldorder information, and Avisynth assumes BFF if the decoder doesn't tell the fieldorder. Check
clip = SegmentedDirectShowSource ("D:\Acquisizioni\conferenza.avi")
# clip = AssumeTFF(clip)
clip = separatefields (clip)
return(clip) and you'll see that all motion goes forth-back-forth-back. Remove the "#", load again, and see that motion now is fluid.
Because of the wrong parity, fields were in wrong order after SeparateFields() (-> 1-0-3-2-5-4-7-6), and your strange combo of trim+select just managed to correct for this error.

Then, you did
a = Lanczos4Resize(a, 704,288)
b = Lanczos4Resize(b, 704,288)
[...]
interleave (a,b)
weave
a simple field resize + weave. This will cause field misalignment, since the necessary field shift (http://forum.doom9.org/showthread.php?p=594339#post594339)*) isn't applied. You tried to correct by a 1 Pixel shift, which is closer to the truth, but not quite exact (overcompensation).

*) correction! (http://forum.doom9.org/showthread.php?p=915260#post915260)


Lastly,
interleave (a,b)
weave
[...]
converttoyv12
you destroyed chroma information by doing a progressive YUY2->YV12 conversion to an interlaced source. :)
(ConvertToYV12(interlaced=true) would've been needed.)


Suggestion: (edit: corrected)
AviSourceIsPreferredOverDirectShowSource(...)
AssumeTFF()
Bob() # fast dumb bob. better use a smart one
Peachsmoother()
Lanczos4Resize(704,576)
ConvertToYV12()
AssumeTFF()
SeparateFields().SelectEvery(4,0,3).Weave()
Trim(...

That's the basic route using basic filters.

il Canoista
11th January 2007, 23:11
Thanks for the very comprehensive answer! I will try now all the corrections, but I must admit that I don't understand why you used Bob in the suggested script...

Didée
12th January 2007, 21:23
Oh, there was still that SeparateFields() in the script ... a copy&paste mistake. ;)
Script is corrected - is it clearer now?

il Canoista
13th January 2007, 00:30
Well... I still dont'understand your script:
1) open the source file with AviSource: OK
2) specify the right order of fields: OK
3) deinterlace the video: it's not ok because I want to leave it interlaced
4) spatio-temporal filtering
5) change resolution
6) convert the video to the colour space used by mpeg2 encoder
7) specify again the field order: it's not ok because the video is progressive after line 3.
8) some processing on the fields of a progressive video: it's not ok.

Maybe it's better if I go and read more guides.
But I have a question: what's the difference between AssumeTFF/AssumeBFF and ComplementParity?

Didée
13th January 2007, 04:27
3) deinterlace the video: it's not ok because I want to leave it interlaced
4) spatio-temporal filtering
..
7) specify again the field order: it's not ok because the video is progressive after line 3.
8) some processing on the fields of a progressive video: it's not ok.
3) de-interlace the video because that's a must, in order to process with a spatial filter in (4).
It's okay because of (8).
..
7) Specify the fieldorder again because Avisynth's bob() filter sets everything to BFF, regardless what it has been before.
Correct fieldorder is necessary because of (8).
8) The bobbed+filtered video is re-interlaced again, i.e. "undo" step (3).


Maybe it's better if I go and read more guides.

Yes and no ... most "guides"-for-something only tell you how to do something. But the important part is not the "how" - the important part is the WHY :

Understanding the problem you must.

Fact is that in an interlaced stream 50% of the real original information is missing - one half of the content is just not there. (!)
Fact is that because of this, processing of interlaced material is tricky.
Fact is that the whole matter is tricky, especially when it gets into the details (of handling it), and I won't even think about trying to cover all aspects here. This forum, and all of the internet is full of information about the topic. And that's where "more reading" indeed is the clue to get a better understanding. ;)


In short:

Well, not all that short ... but didn't you want to read? ;)

An interlaced stream can't shouldn't be processed by spatial filters directly (because the vertical neighbor pixels in fact are temporal neighbors). For spatial operations, the interlaced stream has to be deinterlaced. Possibilities are just separating the fields, or performing bob-deinterlacing.

An interlaced stream can be directly processed by a strictly temporal filter. It's not fully optimal, because of all "moments in time" that the source shows, only every second one is used for filtering; but it won't do much harm in most cases.

However, it's not a very good idea to use temporal filtering after doing SeparateFields(), because temporal neighbors then are spatially misaligned (up-down-jumping) ... in fact, temporal filtering after SeparateFields() is partially similar to spatial filtering of interlaced frames.

Therefore, it's tricky to use a filter that uses spatial *and* temporal filtering together. The minimal solution is to split the even and odd fields into two chains, process both chains with the spatio-temporal filter, then re-interlace the stream:

evn = SeparateFields().SelectEven().SpatioTemporalFilter()
odd = SeparateFields() .SelectOdd() .SpatioTemporalFilter()
interleave(evn,odd).Weave()

That's the minimum to ensure "technically not wrong" spatio-temporal filtering. Problem is that in each chain, the filter is working on only 50% of the information that the stream is carrying ... and since the stream carries only 50% of the information that once has went into the lens of the recording device, it's only 25% of the true initial information. One quarter, three quarters missing ... not very much, isn't it.

That's why bob deinterlacing is the way to do "better" filtering of interlaced content. Basically, (basically!!), a bob filter reconstructs those 50% of information that are missing in the interlaced stream. If so, then after bobbing the stream can be processed like a "normal" progressive source: the bob filter just made the interlaced stream progressive.
Now a spatio-temporal filter can work on 100% of the information in the interlaced stream (instead of only 50% when just separating), and therefore on 50%(*) to 100%(**) of the true initial information (depending on the quality of bobbing) instead of only 25% when just separating.

Of course it's not like just using "bob()" were the magic bullet to make everything perfect. Bob() is a "dumb" filter, it won't restore any of those 50% missing information. Therefore, the spatiotemporal filter works on the 50%(*) subset. On the plus side, it works very fast.

With smart bobbing (also named "motion-adaptive"), it gets better, and it gets slower. Smart bobbers mostly won't help awfully much in moving areas, but they can restore missing information in static areas. The spatiotemporal filter now works somewhere between the 50%(*) and the 100%(**) subset. (On average, much closer to 50% ... it gets difficult to put in numbers, but lets say ... 60-65%.)
Speed impact is quite noticeable.

Then, there are the motion compensated bobbers like MVBob or MCBob. These do even better, but also very much slower. Their aim is restore as much of those 50% information that from the start are missing in the interlaced stream. Ideally, they would bring the spatiotemporal filter to work on the 100%(**) ... but that's only theory. Roughly guessing, let's estimate a range of 65-80%.


Those are the available options, in order of growing quality and growing computational effort. In the end, it depends on the ratio
"processing_time : achieved_quality", and on how much is enough to satisfy.

The minimal solution with separating even/odd, filtering both separately, then re-interlacing isn't the highest-quality method, but it's also the fastest. BY FAR the fastest.

The maximal solution with motion-compensated bobbing will usually deliver the highest-quality result, but it's also very slow. Perhaps 10, perhaps 20, perhaps 30 times slower than the minimal solution. (Imagine: 12 days instead of 12 hours of processing...:D)

***

Mind you ...

a looong time ago, it took me like half a minute to "understand" the idea of interlacing.

Afterwards, it took me several years to really understand interlacing. ;)

And, judging from the past ... (everytime when I thought I finally got it, something happened (usually it was scharfis_brain that "happened" *g*) to show me that I didn't get it yet) ...

... it's quite possible that I still don't understand interlacing. :D

il Canoista
13th January 2007, 13:56
That's a great explanation!
Well, unfortunatly I have an old PC based on Athlon XP 2000, so the better deinterlacing techniques are not accessible to me. Using my script the encoding was already slow (about 7-8 fps), so using advanced bob deinterlacer I will go under 1 fps...

Let's make an incomplete shortened: it's not wrong creating one stream for odd fields, one stream for even fields, and than processing each stream separately, but the temporal filtering will work on 50% of the original temporal information (there is one field every 1/25 of second, while in the original stream there is one field every 1/50 of second).
As far as the spatial filtering there are no differences between separate fields approach and bob approach (I'm considering a dumb bob deinterlacer) since they work on the same amount of informations.

3 more stupid questions:

1) Top field = odd field = the 2n+1 lines of the frame.
2) Bottom field = even field = the 2n lines of the frame.
The lines are numbered from 1, not from 0, so the first line is a top field line. Is it correct?

Another problem is field dominance: which field is displayed first.
The top field can be displayed first, or the bottom field can be displayed first.
If I reverse the lines of a field ( 1<-->2, 3<-->4, ...) and don't change the (temporal) field dominance, I'm changing the order used to display the fields. Assumed that the original video was correct, the result is that the motion goes forward-backward instead of going only forward. From this situation, if I change the field dominance I will get the correct temporal order of the fields, but now the fields are in the wrong spatial position, so I will get a vertical flickering.
Is that correct?

Alain2
13th January 2007, 14:40
As far as the spatial filtering there are no differences between separate fields approach and bob approach (I'm considering a dumb bob deinterlacer) since they work on the same amount of informations.

No, spatial filtering will take into account neighboors vertically as well, and you can have details in one field that would have an influence in the other if bobbed correctly, whereas it would not be seen by filtering a separatfield.selectodd for instance. Imagine an interlaced frame of dots like this:
wwwwwwww (white)
yyyyyyyyyyy (yellow)
ggggggggggg (green)
bbbbbbbbbbb (black)

selectodd will see
wwwwwwww
ggggggggggg

and you're missing the yellow and black in between. Spatial filtering will therefore not take into account the yellow and black,but will mix somehow the white and green, thus you will end up with a mix of white an green above and bellow the yellow, which is probably not wanted

il Canoista
13th January 2007, 15:02
No, spatial filtering will take into account neighboors vertically as well, and you can have details in one field that would have an influence in the other if bobbed correctly, whereas it would not be seen by filtering a separatfield.selectodd for instance.
Well, I was considering the standard bob deinterlacer of Avisynth. It simply expands a field to full resolutions using bicubicresize without taking into consideration lines from other fields.

il Canoista
14th January 2007, 23:54
Update: probably the video is field based, not frame based.
If I use assumefieldbased the video is stable. I tried this in the script suggested by Didée, but Bob deinterlacer doesn't work properly because after it the result is an interlaced frame with twice the original height, so the spatial filtering will give bad results. So I don't know how to filter a field based video.
I also tried the original script suggested by Didée but I noticed that after Bob I have properly deinterlaced frames (and this is good) but there is a vertical oscillation from one frame to the succesive, so I think that this is not good for a temporal filtering.
Maybe It could be interestig to know that the capture card is a FAST AV MASTER.
Here is the Didée's script (but errors are mine...):
DirectShowSource ("D:\Acquisizioni\conferenza.00.avi")
AssumeTFF()
Bob()
Trim(0,103553)
Peachsmoother()
Lanczos4Resize(720,576)
ConvertToYV12()
AssumeTFF()
SeparateFields().SelectEvery(4,1,3).Weave()
...

Didée
15th January 2007, 01:54
Better provide a sample. From what you're describing, I'm not sure if we're in the same show.

Update: probably the video is field based, not frame based.
Meaning of "fieldbased" is unclear. In a sense, every interlaced video is fieldbased. In another, it means every source frame in fact is a field. Did ou record at 50fps?

tried this in the script suggested by Didée, but ...
___

I also tried the original script suggested by Didée
You're talking about two scripts, but I've only posted one in this thread??


If I use assumefieldbased the video is stable. I tried this in the script suggested by Didée, but Bob deinterlacer doesn't work properly because after it the result is an interlaced frame with twice the original height,
On my side, above script does not do that. Unclear. What was your exact script that did double the height?


I also tried the original script ... but I noticed that after Bob I have properly deinterlaced frames (and this is good) but there is a vertical oscillation from one frame to the succesive, so I think that this is not good for a temporal filtering.
With just a dumb bob, vertical oscillation will necessarily happen in static areas. Regarding the final output, this oscillation doesn't matter. But denoising gets less efficient by it. That's why a smart bob deals better.


Here is the Didée's script (but errors are mine...):
DirectShowSource ("D:\Acquisizioni\conferenza.00.avi")
AssumeTFF()
Bob()
Trim(0,103553)
Peachsmoother()
Lanczos4Resize(720,576)
ConvertToYV12()
AssumeTFF()
SeparateFields().SelectEvery(4,1,3).Weave()
...

Exactly the suggested script, just that one correct thing was exchanged by an erroneous:
Why did you put that "1" in SelectEvery()? That is *wrong*.

The suggested script says (4,0,3), and that's what is needed to get all the *original* fields back from the bobbed stream.
With your (4,1,3), the top fields of the final output are not the original top fields (which they should), but the constructed spatial interpolations of the bottom fields, ... not good, no no. :)
(But interesting: it creates "blurry aliasing") :D

il Canoista
15th January 2007, 11:33
Well, avisynth manual makes a distinction between frame based interlaced videos and field based interlaced videos. The manual is not clear, I think that in frame based videos the two fields are stored in one frame, while in field based videos the field are stored indipendently but they are rendered on screen together.
You're talking about two scripts, but I've only posted one in this thread??

You simply get the second script from your script by adding a assumefieldbased after DirectShowSource. In this second script Bob doesn't deinterlace.

With just a dumb bob, vertical oscillation will necessarily happen in static areas. Regarding the final output, this oscillation doesn't matter. But denoising gets less efficient by it. That's why a smart bob deals better.

Ok, so that's normal.

Exactly the suggested script, just that one correct thing was exchanged by an erroneous:
Why did you put that "1" in SelectEvery()? That is *wrong*.

Well, I tried first (4,0,3) and after that tried also every possible combination to see what happens. Just experiments...
Considering that a vertical oscillation is normal after a dumb bob, then your script (the one with (4,0,3)) works.
Well, I think that if I vertically shift one of the field of the frame so that there is no vertical oscillation, apply a temporal filter and then undo the previous vertical shift, then the temporal filtering will work better... Something like my first script, but with only one peachsmoother after interleave and before weave.

Wilbert
15th January 2007, 22:49
Well, avisynth manual makes a distinction between frame based interlaced videos and field based interlaced videos. The manual is not clear, I think that in frame based videos the two fields are stored in one frame, while in field based videos the field are stored indipendently but they are rendered on screen together.
You might need to read: AviSynth25/Docs/english/advancedtopics/interlaced_fieldbased.htm

il Canoista
6th March 2007, 23:30
News about this uninteresting problem: I found that if I use the original mjpeg decoder from the manufacturer (I took it from Win98 driver package and installed it manually) instead of ffdshow I get a smooth video without the strange script in the first message of the thread. So if think that the mjpeg video stream created by the capture card is out of standard and ffdshow can't manage it correctly. This doesn't surprise me because mjpeg is not a standard as DV is.
I must say that the original decoder is slower that ffdshow and works in the RGB colour space (this is strange: mjpeg works in YUV, doesn't it?), wich is bad because I'm using only YUV filters.