NNEDI3
NNEDI3 copied to clipboard
Field order changes go undetected when field=-2
When using double rate output (field=-2), if the clip's field order changes at some point during the clip, nnedi3 doesn't respond to it and just keeps using the same field order that the clip started out with.
Bob and TDeint do not have this issue and respond to the field order changing (example below).
Test clip: https://drive.google.com/file/d/1KdE0np8016zr7ovRassdbH7OtbKU7e-a/view?usp=sharing
# entirely TFF source clip
LWLibavVideoSource("480i 3-2 and 1-1 TFF.mkv", repeat=true)
scene1 = last.Trim(102,224).AssumeTFF() # should appear correct since source is TFF
scene2 = last.Trim(225,393).AssumeBFF() # should appear incorrect if deint filter is obeying
test = scene1 ++ scene2
ScriptClip(test ,
\ """
field_order = GetParity(current_frame)==true ? "TFF" : "BFF"
frame_number = "frame: " + String(current_frame)
SubTitle(field_order + "\n" + frame_number, lsp=10)
\ """, after_frame=true, local=false)
# results:
# bob() # PASS (scene2 appears incorrect, as it should)
# tdeint(mode=1, order=-1) # PASS (scene2 appears incorrect, as it should)
nnedi3(field=-2) # FAIL (scene2 doesn't appear incorrect)
# bwdif(field=-2) also passes the test, but only if I delete the "_FieldBased" frame property
beforehand - implying that bwdif preferences "_FieldBased" over Avisynth's parity flag.
This is not an issue, NNEDI3 doesn't have automatic detection, it just does at the field order you select.
Sorry you're right - the readme just says "starts with" Avisynth field order. It doesn't say it "keeps using" Avisynth field order.
Is it possible to update the field order on every frame inside nnnedi3? I'm just getting into DVDs and have come across NTSC discs where the field order is dynamic. Seems to be more of a thing with soft telecined ones.
The way I'm imagining it, I think it should just be a single line of code to get and set the field order for every input frame. I'm not confident this would break anything given the simple nature of "it takes in a frame, throws away one field, and then interpolates the missing pixels using only information from the kept field".
I can implement this manually in Avisynth runtime environment by creating 2 nnedi3 clips - one with TFF (field=3), the other with BFF (field=2) and choose the output clip based on GetParity() inside ScriptClip.
But I think it would be better to do this inside nnedi3 as I think setting up the 2 nnedi3 clips may cause double CPU usage at certain times due to the way Avisynth prebuffers frames. Say you have a cluster of frames which goes TFF-BFF-TFF-BFF, if Avisynth is prebuffering 3 frames in advance then during this alternating section it may be rendering both clips (or something like this, I don't really know for sure how it works under the hood, but I seem to be seeing higher CPU usage on such sequences, although it's hard to tell because I don't know when nnedi3's prescreener is choosing cubic interpolation which is far less demanding).
I'll see if i can do something, but for now i don't intend to work on my filters before a long time...
No worries.
Actually I think the field order situation is such a mess anyway, that it wouldn't really be much help even if nnedi3 read the field order for every frame, because so many other filters are getting it wrong that it still requires user intervention anyway.
The only source filter which seems to get it correct is LWlibavVideoSource with repeat=true (obeying repeat field flags in source, i.e converting 23.976p soft telecine to 29.97i) . This causes the field order to remain fixed for the whole duration of the clip and the issue can be avoided that way. The same is not true for FFMS2 with rffmode=1 which screws something up with soft telecine DVDs such that the field order it reports to Avisynth is not necessarily the field order of the video frames. Which is strange since they both use ffmpeg as far as I can tell.
Although I think it is still possible within the MPEG2 spec for each frame to have their own field order so it's still not a 100% guarantee that Lwlibaw + repeat=true would avoid the issue in all cases.
PAL DVD's are much friendlier - pretty much all of them are 25i TFF constant framerate with no repeat field flags. Whereas NTSC DVD's can have variable framerate, repeat field flags & dynamic field order all conspiring to screw things up, almost like a form of obfuscation for copy protection or something.
@jpsdr I think this issue need to re-opened, just in case, so then it can be seen so maybe someone can see it and do PR
I don't know when/if i'll try to work on this. If someone make a PR first, it MUSTN'T change the actual behavior, add new modes (-3 and -4) for a new behavior.
Yes, better to extend new feature in its own separate module that doesn't break other things.
Actually QTGMC deinterlacing uses nnedi3 and is currently broken by this issue for clips with dynamic field order.
Vast majority of clips have static field order so I'm guessing that's why people haven't really noticed this issue.
In my mind it should be a simple fix ASSUMING the field order is set in one place and there are are NOT heaps of places where it calculates it.
Is this the relevant bit perhaps?
https://github.com/jpsdr/NNEDI3/blob/ec3d992227cea6fe885c34137385c6a99c9f5c3b/nnedi3/nnedi3.cpp#L1066
PVideoFrame __stdcall nnedi3::GetFrame(int n, IScriptEnvironment *env)
{
int field_n;
if (field>1)
{
if (n&1) field_n = field == 3 ? 0 : 1;
else field_n = field == 3 ? 1 : 0;
}
else field_n = field;
Do we want to set field_n to Avisynth's value for our new field=-3 mode?
I searched the whole repository and this was the only file containing references to field_n.
Note: I have no idea what I'm talking about, I'm just looking at stuff here.