View Full Version : Bob, AssumeFramebased, TFF and parity
Fizick
8th December 2005, 19:31
I remember old thread, where question about bob() was discussed.
See discussion around this post:
http://forum.doom9.org/showthread.php?p=545407#post545407
The Problem: If AssumeFrameBased() really resets the Field order internally to BFF, that's not what i want.
If i have used AssumeTFF i want AVISynth to stay at TFF!
I never used Bob(), but SmoothDeinterlace (doublerate=true) and this Bobber act's like Kernelbob if the correct Field order is given (after AssumeTFF as an example).
If i write my own (dump) Bobber by using AVISynth-Functions, it act's like KernelBob(), not like Bob().
So, from my point of view, Bob() does it wrong, all other Bobbers are doing it correct.
[quote]
Well, if Bob() does it wrong then maybe the Avisynth programmer's can explain it to us?
[/qoute]
I thinked, that this problem is already solved in 2.5.6.
But it seems, it is not the case.
So, here is my suggestion to preserve parity:
class AssumeFrameBased : public GenericVideoFilter
/**
* Class to assume frame-based video
**/
{
public:
AssumeFrameBased(PClip _child) : GenericVideoFilter(_child)
{ vi.SetFieldBased(false); vi.Clear(VideoInfo::IT_BFF); vi.Clear(VideoInfo::IT_TFF); }
inline bool __stdcall GetParity(int n)
{ return child->GetParity(n - (n&1)); } //Fizick (was return false)
inline static AVSValue __cdecl Create(AVSValue args, void*, IScriptEnvironment* env)
{ return new AssumeFrameBased(args[0].AsClip()); }
};
the similar changes for AssumeFieldBased is:
{ return child->GetParity(n - (n&1)) ^ n&1; }//Fizick (was return n&1)
I am also not very understand, why we use:
vi.Clear(VideoInfo::IT_BFF); vi.Clear(VideoInfo::IT_TFF)
May be I am completely wrong?
IanB
8th December 2005, 22:52
Yep it's broken.
The current AssumeFrameBased code is fully resetting everything to default, and as you point out, "is a little bit", "not quite right".
Unfortunatly the more intuitive AssumeTFF() and AssumeBFF() verbs were added when the original parity logic was not very well understood and "doesn't play well with others", if I can find time I might re-write them for 2.6.
For Frame based material GetParity should return False for BFF frames and return True for TFF frames (Yes! You have to support mixed media correctly). i.e. for BFF Frame based clips GetParity should be always returning False and for TFF Frame based clips GetParity should be always returning True.
For Field based material GetParity should return False for bottom fields and True for top fields i.e. for BFF Field based clips GetParity should be returning False for n=0,2,4,... and True for n=1,3,5,... and for TFF Field based clips GetParity should be returning True for n=0,2,4,... and False for n=1,3,5,...
Fizick
9th December 2005, 06:16
IanB,
My suggested code gives results (parity) exactly as you described! (Or not ?)
I use parity of nearest even (0,2,4,...) source frame (or field).
LogicDeLuxe
9th December 2005, 12:27
I did some norm conversions from NTSC to PAL.
Is this the reason, I had to useConvertFPS(50)
SeparateFields
SelectEvery(4,1,2)
Weavewhen using bob(), butConvertFPS(50)
SeparateFields
SelectEvery(4,0,3)
Weavewhen using TDeint(mode=1, mthreshl=4) instead?
I was a bit surprised and also puzzled about the difference.
scharfis_brain
9th December 2005, 12:48
bob() always resets to BFF()
I claimed this SEVERAL times, but nobody noticed it.
TDEINT() passes through the input fieldorder.
leakkernelbob() resets the fieldorder to BFF, too!
I don't know the bahaviour fo Assumeframebased() or plain kernelbob()
IMHO a deinterlacer has to do those things:
- set the framebased flags
- output the correct fieldorder.
currently I am unsure how to interpret the fieldorder flag.
doubleweave() puts out an alternating fieldorder flag.
anybob() puts out a constant fieldorder flag
should the doubleweave() behaviour changed, too
or should bobbers put out alterneting fieldorder flags?
Fizick
9th December 2005, 19:52
Seems, Ianb is busy with 2.6.
So, here is my changed Avisynth 2.5.7 non-official test alpha version for discussion. :)
Please try it.
Changes is in my above post.
http://www.avisynth.org/fizick/temp/avisynth257parity.zip
IanB
11th December 2005, 22:30
No, Ian is busy with the computer industry pre-season panic i.e. Real life :D
As to Bob() and AssumeFrameBased() resetting the Parity environment, I think the logic is that after a Bob (or Assume) the frames are now progressive and TFF/BFF is meaningless or must be explicity redefined. Remember all this is Ben era, where ComplimentParity() ruled and there were no AssumeTFF()/AssumeBFF() verbs.
My initial reaction was that this is "not quite right", but as I read more posts and think a little deaper I am tending back towards the Ben way of thinking. There was an old thread somewhere exploring 4 state parity i.e. [TFF, BFF, Progressive, Unknown] which needs some re-reading. Extreme thinking on this subject is obviously required.
scharfis_brain
11th December 2005, 22:37
I just did a lot of thinking regarding this issue.
This script:
avisource("blah.avi")
assume?ff()
somebob()
separatefields().selectevery(4,0.3).weave()
has to be lossless at any cost.
but it is only lossless with bff input. with tff input one gets a blurred mess.
using TDeint(mode=1) is lossless for both, TFF and BFF.
I am getting tired setting assume?ff() twice in my scripts.
one before bob() and the other one after bob().
It is important to know the fieldorder the stream had befor bobbing in order to select the correct lines in the re interlacing process.
IanB
11th December 2005, 22:43
@Fizick,
Just to help the thinking, your code{ return child->GetParity(n - (n&1)); } //Fizick (was return false)is equivalent to{ return child->GetParity(n & ~1); } // ~1 = 0xfffffffeAnother possibility is{ return child->GetParity(n) ^ !(n&1); }// ^ = XORI am not proposing any of these, I am just poking the "more thinking" button ;)
IanB
11th December 2005, 22:53
@scharfis_brain,
A possibility might be to have AssumeTFF() change the "default" for reset to True. I can see a real mine field growing with convoluted GetParity calculations here.
Thorts?
mg262
11th December 2005, 23:04
Thorts?Have bobbers have the option to output fieldbased content?
scharfis_brain
11th December 2005, 23:22
how should a bobby put out fieldbased video and why?
if one wants the, he can do this:
any_bobber().separatefields()
this will set the fieldbased flag and will put out true fieldbased stuff.
anyway, the fieldorder needs to be set right (the way I showed above) before separatefields() else you're getting into trouble when puzzling them back togother later.
mg262
12th December 2005, 11:00
Ignore that thought -- it had a reason, but I have discardedit in favour of this alternative: replace separatefields().selectevery(4,0.3) with a function
retainfield(clip main, clip reference)
Here main is progressive (output of bobber + whatever processing) and reference is the pre-bobbed clip. The two clips have the same length. Retainfield discards one field in each frame of main, using reference to decide which field to discard. So if the 5th field of reference is a top field, the top field of frame 5 of main is retained. So your script becomes
avisource("blah.avi")
assume?ff()
unbobbed = last
somebob()
retainfield(unbobbed).weave()
That doesn't rely on bobbers being written intelligently, doesn't require field information to be stored in progressive clips (which is a little unnatural as Ian points out) and will also in theory deal with twisted clips where field order doesn't alternate naturally.
scharfis_brain
12th December 2005, 12:53
but this is still more complex to script and te understand (for users being new to that stuff) than a simple
avisource("blah.avi")
assume?ff()
somebob()
reinterlace()
for sure a fieldorder is unnatural for 50p or 59.94p, but it is necessary here to let the process of bobbing and reinterlacing being handled most easy and intuitive.
The previously fieldorder needs to be known when reinterlacing a bobbed (progressive) stream, so why discarding or falsifying this needed information? I will hurt noone if it is transmitted correctly!
IanB
13th December 2005, 10:32
@Scharfis,
So you would be happy with this simple changeto have AssumeTFF() change the "default" for reset to True.
Mug Funky
13th December 2005, 10:42
filters not resetting (or incorrectly setting) framebased, parity, etc are indeed a bit of a minefield.
my advice is to just use "assumeframebased" and "assumetff" a lot, until we can agree on a default behaviour that is less confusing and more workable than the current model (which is just fine if you use workarounds, but it requires a greater understanding of what you are doing, or a smarter script to do it for you).
for example, scharfi's script is lossless both ways if you change it to:
avisource("blah.avi")
assume?ff()
somebob()
assume?ff().separatefields().selectevery(4,0.3).weave()
btw, i noticed that tritical's new EEDI2 doesn't set "frame based" either, which is a bummer if you're using it to "redeinterlace" some video that's been deinterlaced poorly (ie. single-field discard then bilinear upsize).
tritical
13th December 2005, 11:24
The next version of EEDI2 does do a vi.SetFieldBased(false)... I accidently forgot about it in the first release. vi.SetFieldBased(false) is all that TDeint does for both mode 0/1. That behavoir is in contrast to leakkernelbob and avisynth's bob which both internally invoke assumeframebased()... that is why they set the fieldbased flag but also reset the fieldorder and parity. I am with scharfis_brain and think that a bobber should keep the original fieldorder because it is often needed again later in a script.
scharfis_brain
13th December 2005, 14:01
to have AssumeTFF() change the "default" for reset to True.
Sorry I do not understand this :(
Fizick
13th December 2005, 18:47
I am with scharfis_brain too :)
In old pointed above thread I saw other famous members (Wilbert, etc) who support it too :)
I consider current implementation as very old bug.
But it is documented, so it it really feature now :)
But we must fix it at last.
IanB,
"another possibility"
{ return child->GetParity(n) ^ !(n&1); }// ^ = XOR
will results in alternate parities for even and odd frames for this:
Mpeg2Source("...")
Assumeframebased()
I hope, with my suggestion above, assumeframebased will preserve parity in any cases.
Both LeakKernenDeint() and BOB() will preserve parity too.
doubleweave() will produce alternate parities (as it must to do - constant parity will be after SelectOdd).
scharfis_brain (or somebody else),
Does you try my test Avisynth version? Does it give consistant results for you?
Fizick
13th December 2005, 18:52
IanB, probably this old thread has discussion about parity?
http://forum.doom9.org/showthread.php?t=46007
tritical
14th December 2005, 10:00
scharfis_brain (or somebody else),
Does you try my test Avisynth version? Does it give consistant results for you?
I haven't tried it, but the code you posted before operates how I think it should... either
{ return child->GetParity(n - (n&1)); } //Fizick (was return false)
{ return child->GetParity(n & ~1); } // ~1 = 0xfffffffe
would work fine.
My next question is why are Assumeframebased() and Assumefieldbased() clearing IT_TFF and IT_BFF? Or for that matter, what good is the current IsParityKnown() function? Its current operation (only returning true for fieldbased material with IT_TFF or IT_BFF set) seems completely broken to me based on current discussions, and no internal avisynth filter currently uses it.
Also, why is it possible for there to be indeterminate states where both IsTFF() and IsBFF() return the same value? That renders it impossible to call only one cause you have to call both to make sure it is a valid state. As far as I can tell IT_TFF and IT_BFF are only used by IsParityKnown(), IsTFF(), and IsBFF(). No function uses IsParityKnown() and the only functions using IsTFF() and IsBFF() are complementparity(), which does check for indeterminate states, and Info() which does not check for indeterminate states.
The next question then, is what is the point of having IT_TFF and IT_BFF at all? There doesn't currently seem to be one since only complementparity() and info() make use of IsBFF() and IsTFF(). Complementparity only uses that info so that it can reset/set the IT_BFF and IT_TFF bits to the opposite of what they currently are, and info only uses it for display purposes. If any external filter is calling IsBFF or IsTFF I highly doubt they are checking for invalid states. Perhaps things were different at some point in the past :confused:. I suspect the original intent was to only have IT_TFF/IT_BFF set for field based material and to require calling IsParityKnown() before calling either one, but that time seems to have long since passed.
Thus, at the end of my rambling it would appear that it literally doesn't matter whether or not assumeframebased/assumefieldbased clear IT_TFF and IT_BFF because nothing currently uses them for anything meaningful :D.
IanB
14th December 2005, 14:46
@Schafis, @Fizick,to have AssumeTFF() change the "default" for reset to True.Yes, cryptic without any source of reference.
Currently the place in the code (AssumeFrameBased) that "resets" the parity state just does a "return false;" this effectively forces an AssumeBFF().
The idea here was to have the code check the current parity order and return true if TFF is current or return false if BFF is current. Also similarly seed the AssumeFieldBased code.
The question is, is this sufficient? Or, does Fizick's idea of taking the parity from the even frames offer something more? There are certainly legacy issues to consider, even though the current behaviour is annoying at the least, many existing scripts (and applications that generate them) expect the current (mis)behaviour. To protect legacy expectations, AssumeFrame/Fieldbased() could grow an option to copy the TFF/BFF state from the child clip.
@tritical,Unfortunatly the more intuitive AssumeTFF() and AssumeBFF() verbs were added when the original parity logic was not very well understood and "doesn't play well with others",Yes "IT_TFF and IT_BFF" are a crock, they violate a programing fundamental for avoiding conflict i.e. "only store information once!". If you store information more than once, it can become different and you end up with a conflict. We have this in avisynth right here and right now.
IanB
14th December 2005, 15:17
currently I am unsure how to interpret the fieldorder flag.
doubleweave() puts out an alternating fieldorder flag.
anybob() puts out a constant fieldorder flag
should the doubleweave() behaviour changed, too
or should bobbers put out alterneting fieldorder flags?Sorry, I missed this.
Bobbers first. The expected output from a bob operation is a double rate stream of purely progressive frames. The parity is effectivly meaningless (progressive frames, doh!), but I concede it can be usefull to copy the TFF/BFF status from the input clip, and yes the parity probably should be constant.
DoubleWeave() is a little strange but it's behaviour is correct. Consider what it does :- For each field it combines that field with the field before and then with the field after to produce and alternating sequence of BFF interlaced frames and TFF interlaced frames. Hence the alternating parity. The expectation is that a SelectOdd() or SelectEven() will follow yielding either a TFF interlaced stream (parity true) or a BFF interlaced stream (parity false).
mg262
14th December 2005, 16:57
This is all getting very complicated... and as noted it is difficult to know where such things as AssumeFrameBased are used -- though I would love to see a cleaner solution to all this if it is possible without breaking too much.
But, apart from anything else, could we not just modify the code for Bob to be as scharfis wanted (i.e. to be like other bobs)?
scharfis_brain
14th December 2005, 17:13
@Ianb: ahh, I must have been drunken while writing this.
Oy course, Doubleweave() needs to put out alternating parity. If it wouldn't do so the so much appreciated doubleweave().selectodd() won't work anymore correctly.
But Anyhow, now I am in trouble.
I think that the bobbers could need alternating parity, too!
(in theory, need to test this!)
cause if someone does this:
bob()
deleteframe(0)
reinterlacing()
the output will be messed up (all interpolated)! with alternating fieldorder after a bob that shouldn't happen.
Alternating fieldorder will swap the output fieldorder if deleting the first odd-numbered frames within such a bob-reinterlace action, but it won't return interpolated frames.
hmmm. but it will immediatelly swap fieldorder of the autput if deleting a single anywhere IN the video.
Arghhh. this is complicated indeed.
If there are no other convincing, and easy understandable solutions I vote for:
- alternating parity for doubleweave()
- constant, input like parity and assumed framebased video after doing a bob.
tritical
15th December 2005, 17:46
The idea here was to have the code check the current parity order and return true if TFF is current or return false if BFF is current. Also similarly seed the AssumeFieldBased code.
After thinking about it some more, I think that this might be a better solution than using the parity of the even frames. Has anyone considered how things would work if assumeframed only did vi.SetFieldBased(false) and did not implement a special getparity() (i.e. just the default return child->getparity(n) )?
Fizick
15th December 2005, 18:15
tritical,
Really it was my idea too (unpublished) :) - firstly I wanted to use the parity not even frames, but very first (n=0) frame. But i think about caching of frames. That is why i suggest the nearest even.
scharfis_brain,
I think, Bob must return constant parity.
If you trim, you know what do you do. An use other Selecevery(...)
parity is not a flag of "good" or "interpolated" fields, but TFF, BFF.
May be in avisynth 3.0 this will be per-frame property.
But I now think it must be not clip propety, not frame property, but ... line property! :devil:
What if somebody will crop top line, or some middle line of TFF frame?
So, I now really suggest change CROP function to change parity if number of first cropped lines is odd.
(Or it is implemented in 2.5.6 ?)
scharfis_brain
15th December 2005, 21:59
So, I now really suggest change CROP function to change parity if number of first cropped lines is odd.
It is a good idea, but you need to be careful with such fieldorder reversing functionalities.
It's a n00b trap: "my output stutters on TV!"
(Output parity will swap, too)
IanB
18th December 2005, 09:14
Hmmm, webs, weaving, tangled ;)
I think the crop thing is a bit over the top, side effects like this are just to convoluted for all but the most expert AVS users.
Inheriting the current parity on AssumeF....Based although extremely valuable and useful is very definitly not backwards compatible. Someone with some spare time should post a survey in the AVS Users forum along with careful, consise explanations of the pros and cons from this (and other) threads.
Bob uses AssumeFrameBased() internally so I would like it to inherit a better AssumeF....Based logic, but as a fallback it can always be treated individually.
Here is some more food for thought.... perhaps implementing [Progressive, Interlaced TFF, Interlaced BFF, Unknown] can resolve the impasse in a conflict free manner. This could be implemented with or without policy enforcement i.e. "Can't Separate the Field of a Progressive Clip, use AssumeTFF or AssumeBFF first."
Bidoche
19th December 2005, 10:49
May be in avisynth 3.0 this will be per-frame property.It was discussed sometimes ago in the 3.0 thread IIRC.
Here is the current scheme (still can be changed at this point) :
Clips are marked either clip of fields or frames (mixing forbidden)
6 types for frames :
- FIELD_TOP
- FIELD_BOTTOM
- PROGRESSIVE
- FRAME_TFF
- FRAME_BFF
- UNKNOWN
Personally I don't like the unkown type and would rather get rid of it.
That would mean you always must pick a type when creating a frame, which kinda makes sense, no ?
IanB
20th December 2005, 13:25
@Bidoche,
Yep, thats what I was thinking about. The UNKNOWN state could be usefull if we go down the policy enforcement route, typically output from AviSource, et el, is UNKNOWN and must be Assumed[somthing] before any of the Interlaced State sensitive filters will touch it. Sort of like explicit casting in programming languages.
Without the policy enforcment exceptions it is pretty much useless.
2.5.6 has started down the enforcment route with SeparateFields and Weave requiring the right FieldBased state. And I must say, I am pretty glad I got talked into it, now I quite often get pulled up when lashing a script together only to find I was doing something really dumb, in previous version I would just get wierd output that perhaps I didn't notice until after I had burned it to a disk and/or deleted the original.
Bidoche
20th December 2005, 14:15
@IanB
What I don't like is having an 'illegal' value as a valid entry for the FrameType enum.
But I guess I could do it differently :
ie use an optional<FrameType> member for the frame type (ie either no value or a valid one)
And what exactly do you intend by enforcement ?
I could have all frame operations throw until the type is set... is that it ?
IanB
21st December 2005, 23:32
What I don't like is having an 'illegal' value as a valid entry for the FrameType enum.
But I guess I could do it differently :
ie use an optional<FrameType> member for the frame type (ie either no value or a valid one)If we don't go with enforcement the point is mote, "UNKNOWN" is meaningless so why bother with it. If we do choose strict enforcement then enumerating the "UNKNOWN" state is very useful in that it allows source filters, like AVISource, to specify "I do not have a clue, the user must cast/assume the stream manually" otherwise it would have to set a default by guessing. "No value" is really just another state, I have no opinion whether "No value" or "illegal enum" is preferable, I guess it depends on the mood of the coder when they type in the code. ;)
And what exactly do you intend by enforcement ?
I could have all frame operations throw until the type is set... is that it ?Yep, thats about it. Keep throw'ing script exceptions until the user make the script 100% unambiguous. :devil:
Bidoche
27th December 2005, 14:10
If we don't go with enforcement the point is mote, "UNKNOWN" is meaningless so why bother with it.We are on the same line thought here, hence my reluctance with UNKOWN : I was not aware of any enforcement scheme that should be associated .
"No value" is really just another state, I have no opinion whether "No value" or "illegal enum" is preferable, I guess it depends on the mood of the coder when they type in the code. ;)Well I DO have an opinion on that : no value is (always) better than special illegal value
It has to do with which one of the two choices express the best the coder intent
- optional<FrameType> immediately informs (those familiar with optional) that no value is special
- UNKOWN on the contrary does not appears that much different of the other values and that needs to be documented clearly... more easily overlooked
The only situation where a 'special illegal value' is reasonable is when performance matters.
But as you should know, performance matters only ... when performance matters ... (ie when optimizer says it does)
Yep, thats about it. Keep throw'ing script exceptions until the user make the script 100% unambiguous.Sold.
Just have to determine exactly which set of frame operations should throw and which shouldn't (all frame buffers access I guess)
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.