Log in

View Full Version : Port of MPlayer Yadif deinterlace filter (C-Plugin)


Pages : [1] 2 3 4

Fizick
3rd April 2007, 19:16
I do not like deinterlace but i try lo learn C-plugin creation again :)
As an exercise I ported MPlayer Yadif (Yet Another DeInterlacing Filter).
http://www.mplayerhq.hu
http://guru.multimedia.cx/deinterlacing-filters/

It is well MMX assembler opimized but with GNU GCC inline compiler.
Assembler porting is hard task. That is why I use Avisynth C plugin interface and MinGW.

But I have an another question. How to create Avisynth C plugins with Microsoft compiler?
Generaly it does not produce correct function name avisynth_c_plugin_init@4.
MSVC (6,7,8) produces underscored _avisynth_c_plugin_init@4 instead,
and it is not possible to use LoadCPlugin command.
I use avisynth_c.h file from Avisynth 2.5.7 distrib.

The only workaround I found is to use yadif.def file for link:

LIBRARY yadif.dll
EXPORTS
avisynth_c_plugin_init@4=_avisynth_c_plugin_init@4


This way I produce yadif.dll with both _avisynth_c_plugin_init@4 and avisynth_c_plugin_init@4 functions. :)
Is it the only way (besides hex editing of DLL)?

Fizick
4th April 2007, 21:05
I found some bug in v0.1 (parity-related).
Released new v0.2 today.

Mug Funky
5th April 2007, 05:04
coolies. i'll try this one out over easter. if it's faster/more robust than leakkerneldeint i might just make it my preferred one for fast processing :)

Pookie
5th April 2007, 13:56
On a 1080i source

Yadif(mode=0) = 29.97fps

Yadif(mode=1) = 29.97fps

I'll check it again to make sure.

As always, thanks for the plugin Fizick :)

Fizick
5th April 2007, 19:58
yes, not all my plugins are slow :)
But it seems, that all fast of them were originally developed by some other (great) people (like Tom Barry, 'Kassandro', Michael Niedermayer)
:)

akupenguin
6th April 2007, 03:18
Yadif(mode=0) = 29.97fps
Yadif(mode=1) = 29.97fps
Yes, it doubles the number of frames but forgets to set the framerate accordingly.

Fizick
6th April 2007, 04:18
Yes, I forget about it.
use assumefps :)

Fizick
6th April 2007, 21:09
Fixed bugs with bob-fps and finally with parity in v0.3

scharfis_brain
7th April 2007, 00:12
hmm this seems to become my preferred filter for quick and dirty conversions.

so far as I could conclude form looking at the results for ióne minute, I think it has the following impementations:

- edi-interpolation similar to tomsmocomp
- temporal motion masking over 5 fields in temporal
- soft motion masking, i.e. no hard thresholding

tritical
7th April 2007, 01:57
You're pretty close for only a minute of watching... pseudo code for what it does (Fizick correct me if I'm wrong, I only glanced at the source code):

temporal sequence of pixels (trying to create pixel 'x'):

c h
a f k
d x i
b g l
e j

int p0 = (c+h)/2;
int p1 = f;
int p2 = (d+i)/2;
int p3 = g;
int p4 = (e+j)/2;

int tdiff0 = abs(d-i);
int tdiff1 = (abs(a-f)+abs(b-g))/2;
int tdiff2 = (abs(k-f)+abs(g-l))/2;

int diff = max3(tdiff0,tdiff1,tdiff2);

int spatial_pred = edi_value;

if (mode < 2)
{
int max = max3(p2-p3,p2-p1,min(p0-p1,p4-p3));
int min = min3(p2-p3,p2-p1,max(p0-p1,p4-p3));
diff = max3(diff,min,-max);
}

if (spatial_pred > p2 + diff)
spatial_pred = p2 + diff;
if (spatial_pred < p2 - diff)
spatial_pred = p2 - diff;

x = spatial_pred;


edi_value is determined by:

trying to create pixel 'x' from neighboring lines:


a b c d e f g
x
h i j k l m n

int spatial_pred = (d+k)/2;
int spatial_score = abs(c-j)+abs(d-k)+abs(e-l);

int score = abs(b-k)+abs(c-l)+abs(d-m);
if (score < spatial_score)
{
spatial_pred = (c+l)/2;
spatial_score = score;
score = abs(a-l)+abs(b-m)+abs(c-n);
if (score < spatial_score)
{
spatial_pred = (b+m)/2;
spatial_score = score;
}
}
score = abs(d-i)+abs(e-j)+abs(f-k);
if (score < spatial_score)
{
spatial_pred = (e+j)/2;
spatial_score = score;
score = abs(e-h)+abs(f-i)+abs(g-j);
if (score < spatial_score)
{
spatial_pred = (f+i)/2;
spatial_score = score;
}
}

Mug Funky
7th April 2007, 02:28
ooh, this is a very sensitive deinterlacer - it'll pick up an interlaced fade in over 200 fields without passing through combs, but it'll also leave static stuff static. it's also more than twice as fast as tdeint and doesn't require vinverse afterward to guard against stray combs.

i might just plop this into my generic standards converter and see what kind of speedup it gives me.

[edit]

btw, i seem to only be able to load it with Load_Stdcall_plugin, as opposed to loadcplugin. not a big deal, but for a while i was quite confused :|

DSP8000
7th April 2007, 04:57
To my eyes this deinterlacer does a very good job, works better than TDeint, faster too. Very simple parameters. Bob mode works well.
scharfi, would you recommend this deinterlacer for quick crop, resize, denoise, reinterlace. I use TDeint for now, simple Bob seems like is blurring too much.
LoadCPlugin works for me.
Thanks for the plugin Fizick :)

tateu
7th April 2007, 22:27
Yes, thanks...this looks like it is going to be my new standard deinterlacer. And the latest 0.3 version fixed my problem with bottom field first clips.

Terka
9th April 2007, 12:00
cant load
LoadPlugin("C:\Program Files\AviSynth\plugins\yadif.dll")
do i need some more dlls?

Fizick
9th April 2007, 12:05
Terka,
more reading of doc is required...

scharfis_brain
9th April 2007, 17:57
fizick, could you alter yadif in a way so it has an additional parameter like TDeint's edeint?

so we could use its pretty good motionmasking with kernel or eedi2 interpolation.

Fizick
9th April 2007, 20:44
scharfis_brain,
No.
Yadif is yadif. Let's not slowdown it.

scharfis_brain
9th April 2007, 22:53
why slowdown?
if the external clip is not given it still will run the max. speed....

ChiDragon
10th April 2007, 02:33
Looks like a nice deinterlacer, but the order=-1 setting is still using the wrong parity with v0.3 for me, and like Mug Funky said it will only load with Load_stdcall_plugin. Also, not a big deal, but the HTML file is missing the CSS since it points to a location that doesn't exist on my computer...

Fizick
10th April 2007, 04:53
ChiDragon,
probably LoadCplugin is overrided by some other old C plugin and LoadPlugin("avisynth_c.dll") command in your system?
Load_stdcall_plugin command was introduced in Avisynth for such case.

order=-1 is wrong with TFF or BFF clip?

ChiDragon
10th April 2007, 06:25
I see, I didn't know that avisynth_c.dll was no longer necessary. It's a TFF vid.

tateu
10th April 2007, 07:16
It's a TFF vid.
Did you add AssumeTFF() before deinterlacing? If you did not, AviSynth is probably treating your video as BFF. Order = -1 works fine here for both TFF and BFF, if I set the parity of the script correctly.

IanB
10th April 2007, 12:51
avisynth_c.dll will still be needed for any older C plugins linked against it.

C plugins linked directly against the core avisynth.dll (i.e Yadif, etc) do not need it.

ChiDragon
10th April 2007, 23:36
It's already seen as TFF, tateu, since it's an MPEG2 with DGDecode. Info() confirmed this.

tateu
11th April 2007, 00:25
It's already seen as TFF, tateu, since it's an MPEG2 with DGDecode. Info() confirmed this.
Yes, you are absolutely correct. Sorry about that. I always use AssumeTFF or BFF in my scripts and I did not check what happens when I leave it out.

If Parity = "Top Field First" then yadif works incorrectly.
If Parity = "Assumed Top Field First" then yadif works correctly.

ChiDragon
11th April 2007, 03:44
I see why... Yadif is using "IsTFF" instead of the GetParity function. Looking at the source for the Info filter it seems that Is_FF is only set by the Assume_FF function (that's how Info checks whether it is "_ Field First" or "Assumed _ Field First"). So everything that isn't explicitly set with Assume returns as BFF.

Fizick
11th April 2007, 04:52
Thanks. Open source is good thing :)
(Mplayer uses "TFF" and "parity" different way than avisynth. It is source of this mess.)

Terka
11th April 2007, 13:21
readed the doc again, but still cant find why cant load
LoadPlugin("C:\Program Files\AviSynth\plugins\yadif.dll")

Leak
11th April 2007, 13:25
readed the doc again, but still cant find why cant load
LoadPlugin("C:\Program Files\AviSynth\plugins\yadif.dll")
Which part of
Implemented as Avisynth C-plugin (not regular Avisynth plugin).
Must be loaded with Load_Stdcall_plugin("yadif.dll") or LoadCplugin("yadif.dll"). Do not use autoloading.
straight from the documentation (http://avisynth.org.ru/yadif/yadif.html) is so hard to understand? :confused:

Terka
11th April 2007, 13:38
sorry:stupid:

Fizick
11th April 2007, 17:45
Released Yadif version 0.4:
Finally (!) fixed bug with wrong used parity for TFF without AssumeTFF.
Removed limitation on frames pitches equality.

about avisynth.css file: place it to upper level folder of plugins dir, for example to "C:\Avisynth 2.5\"

(Field parity is still strange thing in Avisynth. For example, why FlipVertical does not change it automatically?)

Fizick
11th April 2007, 18:25
Some speed test with PAL DVD source, null encoder codec:
avs2avi.exe yadif.avs -o n -c null

Tomsmocomp(-1,5,0) - 59.32 fps
LealKernelDeint(1) - 51.80 fps
Yadif() - 40.30 fps
TDeint() - 16.40 fps

(AthlonXP 2040MHz, SDR Dimm)

jeffy
11th April 2007, 22:36
Some speed test with PAL DVD source, null encoder codec:
avs2avi.exe yadif.avs -o n -c null

Tomsmocomp(-1,5,0) - 59.32 fps
LealKernelDeint(1) - 51.80 fps
Yadif() - 40.30 fps
TDeint() - 16.40 fps

(AthlonXP 2040MHz, SDR Dimm)

Could you please share your sample source file and script, if at all possible? If yes, what version of avs2avi did you use? Thank you in advance, I... I like it!

Fizick
12th April 2007, 04:34
script:

load_stdcall_plugin("yadif.dll")
mpeg2source("g:\vts_06_1.d2v")
yadif()

avs2avi v1.39
source - (PAL DVD 720x576, 25)
It is not encoding example. It is speed test.

LoRd_MuldeR
12th April 2007, 15:10
btw, i seem to only be able to load it with Load_Stdcall_plugin, as opposed to loadcplugin. not a big deal, but for a while i was quite confused :|

No, you are not :)
LoadPlugin results in "Not a valid Avisynth 2.5 Plugin" error message. Load_Stdcall_Plugin works fine.

Boulder
12th April 2007, 16:31
Notice the tiny c in Mug Funky's loadcplugin ;)

And thanks, Fizick, I really have to donate for this and MVTools as soon as my paycheck arrives.

Fizick
12th April 2007, 18:50
(May be I am wrong) Avisynth support 4 types of plugins:
1. Regular plugins. Use LoadPlugin(...)
2. VirtualDub plugins. Use LoadVirtualDubPlugin(...)
3. Vfapi plugins. Use LoadVFapiPlugin(...)
4. Avisynth_C plugins with two subtypes:
4.1 Original Kevin Atkinson C-interface plugin. (It use C language calling syntax internally). Use LoadCPlugin(...) (note C symbol in word!)
You must firsly load Avisynth_C interface by LoadPlugin("avisynth_c.dll").
4.2 Updated (new) C-interface plugin. (It use stdcall calling syntax internally). Use Load_Stdcall_plugin(...) or LoadCPlugin(...).
Such plugins are not need in avisynth_c.dll anymore (since v2.5.6? avisynth has core function LoadCPlugin).

So, If you need in some old Avisynth_C plugin, for example SmartDecimate, you must firstly load Avisynth_C.dll.
This Avisynth_C.dll has function LoadCPlugin which will override core Avisynth function with the same name LoadCPlugin.
In this case, LoadCPlugin command will load old-style C-plugin only.
Load_Stdcall_plugin will NOT overrided, and may be used in any case with new C-plugins (like Yadif).

(In my opinion, it is not very good. LoadCPlugin word could be removed fom core or reserved for old-style C-plugins only.
But we have what we have now).

Advice for users: use Load_stdcall_plugin(...) for new C-plugins, and LoadCPlugin(...) for old C-plugins.
Advice for developers of C-plugins: use stdcall type, new avisynth_c.h header and avisynth.lib library provided with avisynth 2.5.7. It works. Tested and approved :)

LoRd_MuldeR
12th April 2007, 19:23
Fizick, did you ever think of porting this to Avidemux, too?
Avidemux has a new Plugin interface now for 'External' filters, but I didn't see any of them yet.
Yadif would be a nice one to have :)

g3power
13th April 2007, 00:01
Fizick, Michael recommends using mcdeint in conjuction with yadif. Do you plan to add mcdeint to your port?

LoRd_MuldeR
13th April 2007, 00:08
Fizick, Michael recommends using mcdeint in conjuction with yadif. Do you plan to add mcdeint to your port?

Did you ever try mcDeint in MPlayer/Mencoder/Avidemux ???
It's slooooooooooooooooooooooooooooow and I can't get satisfactory quality out of it...

g3power
13th April 2007, 00:55
Yes. I did that just a few hours ago. It was slow (aprox. 1-2 fps). The quality was very good, though.

I have been experimenting with 50i->50p for a few month now. The best way I have found until now seems to be Apple Compressor with deinterlacing quality set to better or best. This uses optical flow and is quite slow on both my G5 and Intel machine. It takes about 25x real-time.

With quality set to "fast" (5x real-time) there are very annoying horizontal temporal artefacts in a very short piece of the footage with a barn in the background made out of wooden planks and the camera on a tripod. The same applies to all other methods I have tried.

As the best method I have found to remove the strong video noise from the footage is to use fizick's great fft3d set to an insanely high strength I was looking for a way to get 50i->50p right in AviSynth...

LoRd_MuldeR
13th April 2007, 18:56
Yadif is now available in Avidemux too, thanks to the work of Fizick and Mean:
http://forum.doom9.org/showthread.php?p=988615#post988615

:thanks:

LoRd_MuldeR
15th April 2007, 11:50
This post is from Avidemux Board and might be of interest:

In Fizick version there is maybe a bug

Original
if (n< (&p->vi)->num_frames)
next = avs_get_frame(p->child, n+1); // get next frame
else
next = avs_get_frame(p->child, (&p->vi)->num_frames-1); // get last frame
I think it should be

if (n< (&p->vi)->num_frames-1) <<<<===
next = avs_get_frame(p->child, n+1); // get next frame
else
next = avs_get_frame(p->child, (&p->vi)->num_frames-1); // get last frame

ChiDragon
15th April 2007, 23:47
Yeah it should be num_frames-1, since a clip with only frame 0 has num_frames=1, one with frames numbered 0-999 has num_frames=1000, etc. Weird that the actual GetFrame call is correct while the If is wrong. :P

Fizick
16th April 2007, 04:47
yes, but Avisynth has internal protection anyway (IMO).
Here is a little more serious problem - processing must be modified for very first and very last frame. May be in some time I will update it.

MuLTiTaSK
16th April 2007, 23:46
DGindex reported my source field order as top and frame rate as 29,97fps i have field operation set to honor pulldown flags so would my script deinterlace my clip and keep the same frame rate i really want to give this filter a try i been hearing so many good things about it i read the manual and think i got it right i just want to make sure with the pros first before i waste a bunch of hours i hope someone can help me thanks in advance :)

http://i10.tinypic.com/2w1xenn.png

SetMTMode(2)
Load_Stdcall_plugin("C:\Program Files\AviSynth 2.5\plugins\yadif.dll")
DGDecode_mpeg2source("G:\CAPS\funny budlight clips.mpg",info=3)
ColorMatrix(hints=true,interlaced=true)
yadif(order=1)
crop( 6, 0, -20, -54)

LanczosResize(640,432) # Lanczos (Sharp)

Fizick
17th April 2007, 04:41
Script is look correct (you may omit order=1 parameter - yadif can get field parity from DGGecode)
But I do not know about MT compatibility.
Yes, Yadif is for real video interlaced sources.
For another case (real NTSC FILM source with puldown) use another deinterlacer (IVTC).
Yadif is new (Avisynth) filter,
so please post your results here.

MuLTiTaSK
17th April 2007, 15:39
Script is look correct (you may omit order=1 parameter - yadif can get field parity from DGGecode)
But I do not know about MT compatibility.
Yes, Yadif is for real video interlaced sources.
For another case (real NTSC FILM source with puldown) use another deinterlacer (IVTC).
Yadif is new (Avisynth) filter,
so please post your results here.

thanks for replying Fizick i changed my script after reading your
post i played it in MPC & VDubMod it looked good and was very fast i'am impressed so far i'am gonna encode some clips with it and post some results on here thanks for porting this gem into
the Avisynth world :thanks:

SetMTMode(2)
Load_Stdcall_plugin("C:\Program Files\AviSynth 2.5\plugins\yadif.dll")
DGDecode_mpeg2source("H:\yadif_tests\funny_budlight_clips.mpg")
yadif()
crop( 8, 0, -20, -54)

LanczosResize(640,432) # Lanczos (Sharp)
#denoise

Fizick
17th April 2007, 20:13
v0.5 fixed the bug

ChiDragon
17th April 2007, 22:35
if (n>0)
prev = avs_get_frame(p->child, n-1); // get previous frame
else if ((&p->vi)->num_frames > 0)
prev = avs_get_frame(p->child, 1); // next frame
else
prev = avs_get_frame(p->child, 0); // cur 0 frame for one-frame clip

if (n < (&p->vi)->num_frames - 1)
next = avs_get_frame(p->child, n+1); // get next frame
else if ((&p->vi)->num_frames > 1)
next = avs_get_frame(p->child, (&p->vi)->num_frames - 2); // prev frame
else
next = avs_get_frame(p->child, 0); // cur 0 frame for one-frame clip

Not saying it's wrong, but why are you getting next for prev and prev for next instead of current for both when there's an out-of-bounds access?

Also shouldn't "else if ((&p->vi)->num_frames > 0)" be "> 1" to check for a 1-frame clip? i.e. wouldn't "(&p->vi)->num_frames > 0" always return 1 if the clip has video at all?