Log in

View Full Version : Passing the field parity correctly


FranceBB
11th December 2020, 10:51
Hi,
I'd like to get and pass the field parity correctly from ffms2 inside Avisynth.
In clip properties, there are IsFieldBased() and GetParity() but there's a problem.
All clips inside Avisynth as they're indexed are framebased unless we manually change it by writing things like AssumeFieldBased(), so the bool IsFieldBased() is kinda useless in my case as it would always return false.
For GetParity() the story is different, 'cause it works both with Frame Based clips and Field Based Clips, so, even if ffms2 doesn't set the fieldbased flag, is not a big deal, 'cause it does set the TFF flag, so GetParity correctly returns true if the frame analyzed is top field first and false otherwise. This is a problem, though, 'cause "otherwise" can mean two things: either that the stream is bottom field first or that it's progressive. Is there a way to get whether a stream is interlaced or progressive automatically? Don't you think indexers should honor the flags and set AssumeFieldBased() when dealing with interlaced stuff instead of treating everything as frame based?

For the records, I tried LSMASH as well by calling LWLibavVideoSource and it doesn't set the flag either.

LWLibavVideoSource("interlaced_test.mxf")
IsFieldBased() ? Subtitle("Fields") : last

always returns false, therefore it just shows the video

LWLibavVideoSource("interlaced_test.mxf")
GetParity() ? Subtitle("Fields") : last

does show the word "Fields" on the top left for TFF and it doesn't show it for progressive files, however it doesn't show it for BFF files either...

real.finder
11th December 2020, 11:00
frame properties _FieldBased maybe is what you need

FranceBB
11th December 2020, 11:16
Isn't it going to work only if the user set it via AssumeFieldBased()?

real.finder
11th December 2020, 11:59
Isn't it going to work only if the user set it via AssumeFieldBased()?

AssumeFieldBased has to do with clip properties

_FieldBased has to do with frame properties

clip properties has nothing to do with frame properties, they are two separate worlds

frame properties is taken from VS (there were plan to do this in vanilla Avisynth before avs 2.6 but didn't done)

FranceBB
11th December 2020, 12:41
You mean in the C++ API Interface?

Like:


int image_type;

enum {
IT_BFF = 1<<0,
IT_TFF = 1<<1,
IT_FIELDBASED = 1<<2
};


in the image properties?

'cause I know that things like

bool IsParityKnown() const;

in the C++ API are only gonna work if it has been set by the user. Can you confirm that

bool IsFieldBased() const;

in the C++ API works with ffms2 and LSMASH without specifying it?
Otherwise, if I didn't get it right, what do you mean with _FieldBased?

real.finder
11th December 2020, 13:45
it's

####### field based #######
"progressive" (0)
"top_field" (2)
"bottom_field" (1)

source and more info https://github.com/Asd-g/AviSynthPlus-Scripts/blob/4bcadba3c1ddfadc28536f38861a3ae6a5224037/LWLInfo.avsi#L4 (don't know if they are in avs wiki)

it can also used in avs script https://github.com/Asd-g/AviSynthPlus-Scripts/blob/4bcadba3c1ddfadc28536f38861a3ae6a5224037/ComparisonGen.avsi#L97 more info https://forum.doom9.org/showthread.php?p=1909566#post1909566 (I think they not added to the wiki yet)

keep in mind that you need updated LSMASHSource https://forum.doom9.org/showthread.php?p=1926057#post1926057 or/and ffms2 https://forum.doom9.org/showthread.php?p=1928993#post1928993

jordanh
11th December 2020, 15:29
Ohh thats amazing functions!
To be honest, FranceBB opened this topic actually for me and it went into a wrong direction so i'll try to clear things up:
What we want to do here is to patch the ffmpeg avisynth demux plugin which means of course we underly lots of restrictions, e.g. backward compatibility and such.
The goal is to tell ffmpeg which field order the finally returned clip has got so it can set up internal filter engine stuff automatically and one does not have to script this part anymore.

Currently, from the C api i use avs_is_parity_known and avs_is_tff functions, they work when the avs script contains the AssumeFieldbased and AssumeTFF/BFF functions.
But after all i wondered if i could go one level deeper and even set the field order when the user did not contain the Assume functions in his script.

On my way i recognized that avs_get_parity(env,framenum) will actually work without the Assume* functions, in difference to avs_is_parity_known it will decode a frame but that might be something worth to sacrifice.
The only problem left is that avs_is_field_based from the C API will always return false if there are no Assume* functions, so from my understanding i could use this logic go be most accurate:

1) we have TFF when avs_get_parity is true
2) otherwise we have UNKNOWN (i can set this in ffmpeg)
3) Except avs_is_bff is set, in that case we have Bottom Field (but it only works when Assume* functions are in the avs script)

I believe above should be safe and work with all source plugins.
What i am not sure of is if this is really all i can do and if its reliable to say we have TFF when avs_get_parity is true but avs_is_field_based is false.

jordanh
17th December 2020, 09:24
...we have TFF when avs_get_parity is true but avs_is_field_based is false?

Sorry to bump this, i hoped it was easy to answer...
Just to make it clear, i am talking about these 2 functions from the C API:

AVSC_API(int, avs_get_parity)(AVS_Clip *, int n);
AVSC_INLINE int avs_is_field_based(const AVS_VideoInfo * p)

StainlessS
17th December 2020, 14:15
I dont know C interface at all, but for CPP interface, can be useful to lookup old v2.58 baked header,
before 2.60 and AVS+ 'un-baked' the headers. [see the v2.58 C header]

From v2.58 CPP header


// From VidioInfo

enum {
IT_BFF = 1<<0,
IT_TFF = 1<<1,
IT_FIELDBASED = 1<<2
};

bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); }
bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); }
bool IsBFF() const { return !!(image_type & IT_BFF); }
bool IsTFF() const { return !!(image_type & IT_TFF); }

// from IClip
/ Base class for all filters.
virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame

// instantiable null filter
//class GenericVideoFilter : public IClip {
bool __stdcall GetParity(int n) { return child->GetParity(n); }

jordanh
20th February 2021, 13:12
After lots of thinking, it now looks like an external application receiving the frames can only threat the frames as interlaced when the following conditions are met:
1) IsFieldBased() == true
2) IsBFF() or IsTFF() == true

Essentially that renders to IsParityKnown() == true.
The reason for IsFieldBased must be true (instead of isFrameBased) is that separatefields forces fieldbased and after weave we have framebased again. A single frame can only be "interlaced" from a 3rdparty app's perspective when both fields are contained in one frame. If the fields are in separate frames, (which means fieldbaesd from avisynth perspective) the material is progressive from 3rdparty perspective.

jordanh
21st February 2021, 23:23
as there have been internal questions about it, here some (hopefully) explainative images about it.
This example assumes the input file is 25i. This means that most source plugins like ffms will return the clip as framebased and progressive (even if it is actually interlaced).

Lets look at the Separatefields() function, assuming that the source plugin decides not to inform the environment about the field order (therefore we must analyze the source file on our own and set assumeTFF or BFF on our own)

Watch how the isFieldBased and/or isFrameBased flag behaves:

https://i.ibb.co/sRfxGcR/assume.jpg (https://ibb.co/F3rZMc3)

Looking at this first picture, if this "clip" is returned finally to the calling 3rdparty appliacation, the final clip is progressive, 50p and half height of the original source. Framebased == false

https://i.ibb.co/bQryZg0/weave.png (https://ibb.co/GnV1Lv6)

After Weave() we have 25i again. Framebased == true

Again, the FINALLY RETURNED PICTURE CAN ONLY BE INTERLACED from the receiveing 3rdparty applications perspective when it is FRAMEBASED. In the case it is FIELD based, it must automatically be progressive from the perspective of the application receiving the final frame.

i belive the trick here is to forget about how avisynth internally thinks about fields and interlacing and to focus on what the finally returned output clip looks like from perspective of the 3rdparty application.