diff mbox

[FFmpeg-devel] reitnerlace - tinterlace-like filter under LGPL

Message ID 841b6c38-b53a-e93f-fb7f-c8c89575eaf0@tremend.com
State Superseded
Headers show

Commit Message

Vasile Toncu March 5, 2018, 11:27 a.m. UTC
Hello,

Thanks for the review. I've made changes according to your guidance.

It would be great to know if the community will go on with our intention 
of adding reinterlace as a alternative for tinterlace.

That being said, here is the new patch.

Regards,

-Vasile Toncu


From 7419be6fa213383ed0908976eedfb963837ed738 Mon Sep 17 00:00:00 2001
From: Vasile Toncu <vasile.toncu@tremend.com>
Date: Mon, 12 Feb 2018 14:16:27 +0200
Subject: [PATCH] Added reitnerlace filter.

---
  libavfilter/Makefile                  |   1 +
  libavfilter/allfilters.c              |   1 +
  libavfilter/reinterlace.h             | 141 +++++++
  libavfilter/vf_reinterlace.c          | 757 
++++++++++++++++++++++++++++++++++
  libavfilter/x86/Makefile              |   1 +
  libavfilter/x86/vf_reinterlace_init.c | 101 +++++
  6 files changed, 1002 insertions(+)
  create mode 100644 libavfilter/reinterlace.h
  create mode 100644 libavfilter/vf_reinterlace.c
  create mode 100644 libavfilter/x86/vf_reinterlace_init.c

+#endif
\ No newline at end of file

Comments

Paul B Mahol March 5, 2018, 11:37 a.m. UTC | #1
On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
> Hello,
>
> Thanks for the review. I've made changes according to your guidance.
>
> It would be great to know if the community will go on with our intention
> of adding reinterlace as a alternative for tinterlace.
>
> That being said, here is the new patch.

As already said, this is not acceptable.

There is no point in having 2 filters with near same funcionality.
Carl Eugen Hoyos March 5, 2018, 12:48 p.m. UTC | #2
2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>> Hello,
>>
>> Thanks for the review. I've made changes according to your guidance.
>>
>> It would be great to know if the community will go on with our intention
>> of adding reinterlace as a alternative for tinterlace.
>>
>> That being said, here is the new patch.
>
> As already said, this is not acceptable.
>
> There is no point in having 2 filters with near same funcionality.

If you consider the new filter ok, the existing filter will be removed
in the same push. I believe sending only the new filter makes
reviewing easier.

Please comment, Carl Eugen
Paul B Mahol March 5, 2018, 12:53 p.m. UTC | #3
On 3/5/18, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>> Hello,
>>>
>>> Thanks for the review. I've made changes according to your guidance.
>>>
>>> It would be great to know if the community will go on with our intention
>>> of adding reinterlace as a alternative for tinterlace.
>>>
>>> That being said, here is the new patch.
>>
>> As already said, this is not acceptable.
>>
>> There is no point in having 2 filters with near same funcionality.
>
> If you consider the new filter ok, the existing filter will be removed
> in the same push. I believe sending only the new filter makes
> reviewing easier.

I'm ok with that, but next commits that do that and also do rename are
not available.

I'm also not sure can reinterlace filter be cosidered really safe from
standpoint that
it does not use any old GPL code.

Also bunch of stuff it does is trivial, both new and old GPL code so I
consider nobody
should care about its license.
Vasile Toncu March 5, 2018, 5:38 p.m. UTC | #4
Hello,


The reinterlace behaves just like the tinterlace and in terms of fps is 
basically the same.

The ASM Opts are used with reinterlace only in case of CONFIG_GPL enabled.

There are two new modes, MODE_MERGE_BFF and MODE_MERGE_TFF for which I 
have documentation.

Also reinterlace processes the planes of a frame in separate threads.

I've tested it with diferent video formats, and the outputs are correct.

Previously there have been acceptance for using some methods form 
tinterlace. Those methods have nothing to do with old, GPL licensed 
code, and are doing some trivial stuff. One can check thread starting at 
[1].

[1] http://ffmpeg.org/pipermail/ffmpeg-devel/2018-February/224941.html

On 3/5/2018 2:53 PM, Paul B Mahol wrote:
> On 3/5/18, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>> Hello,
>>>>
>>>> Thanks for the review. I've made changes according to your guidance.
>>>>
>>>> It would be great to know if the community will go on with our intention
>>>> of adding reinterlace as a alternative for tinterlace.
>>>>
>>>> That being said, here is the new patch.
>>> As already said, this is not acceptable.
>>>
>>> There is no point in having 2 filters with near same funcionality.
>> If you consider the new filter ok, the existing filter will be removed
>> in the same push. I believe sending only the new filter makes
>> reviewing easier.
> I'm ok with that, but next commits that do that and also do rename are
> not available.
>
> I'm also not sure can reinterlace filter be cosidered really safe from
> standpoint that
> it does not use any old GPL code.
>
> Also bunch of stuff it does is trivial, both new and old GPL code so I
> consider nobody
> should care about its license.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Thomas Mundt March 6, 2018, 6:38 p.m. UTC | #5
Hi,

2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:

> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
> > On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
> >> Hello,
> >>
> >> Thanks for the review. I've made changes according to your guidance.
> >>
> >> It would be great to know if the community will go on with our intention
> >> of adding reinterlace as a alternative for tinterlace.
> >>
> >> That being said, here is the new patch.
> >
> > As already said, this is not acceptable.
> >
> > There is no point in having 2 filters with near same funcionality.
>
> If you consider the new filter ok, the existing filter will be removed
> in the same push. I believe sending only the new filter makes
> reviewing easier.
>

For me reviewing would be easier when Vasile sends a patchset that includes
the replacement of tinterlace filter.
That way existing fate tests could be used which are fortunately pretty
extensive in this case.
Also it would be helpful when you and/or other experienced ffmpeg
developers would clarify first which parts of tinterlace have to be
rewritten for proper relicensing.
Being left in the dark makes working on patches frustrating.

Another question is how to deal with vf_interlace? IMHO for the user there
should be no difference in output, speed and license.
Two options:
1. Relicensing and slice threading will also be ported to vf_interlace
2. The commands from vf_interlace will be included in the new tinterlace
filter. vf_interlace will be deleted together with old tinterlace filter

I would prefer the second option, but maybe there are even better options
that don´t come to my mind.

Please comment.
Thanks,
Thomas
Carl Eugen Hoyos March 6, 2018, 11:46 p.m. UTC | #6
2018-03-05 13:53 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
> On 3/5/18, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>> Hello,
>>>>
>>>> Thanks for the review. I've made changes according to your guidance.
>>>>
>>>> It would be great to know if the community will go on with our intention
>>>> of adding reinterlace as a alternative for tinterlace.
>>>>
>>>> That being said, here is the new patch.
>>>
>>> As already said, this is not acceptable.
>>>
>>> There is no point in having 2 filters with near same funcionality.
>>
>> If you consider the new filter ok, the existing filter will be removed
>> in the same push. I believe sending only the new filter makes
>> reviewing easier.
>
> I'm ok with that, but next commits that do that and also do rename are
> not available.

It should have been a former (not a next) commit that I considered
trivial but I see now that because of fate it makes sense to add and
remove in one patch.

> I'm also not sure can reinterlace filter be considered really safe from
> standpoint that it does not use any old GPL code.

Not sure I understand:
Do you mean that the new filter was not independently written?

> Also bunch of stuff it does is trivial, both new and old GPL
> code so I consider nobody should care about its license.

That does not sound like a safe approach.

Carl Eugen
Carl Eugen Hoyos March 6, 2018, 11:49 p.m. UTC | #7
2018-03-06 19:38 GMT+01:00, Thomas Mundt <tmundt75@gmail.com>:
>
> 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>
>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>> > On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>> >> Hello,
>> >>
>> >> Thanks for the review. I've made changes according to your guidance.
>> >>
>> >> It would be great to know if the community will go on with our
>> >> intention
>> >> of adding reinterlace as a alternative for tinterlace.
>> >>
>> >> That being said, here is the new patch.
>> >
>> > As already said, this is not acceptable.
>> >
>> > There is no point in having 2 filters with near same funcionality.
>>
>> If you consider the new filter ok, the existing filter will be removed
>> in the same push. I believe sending only the new filter makes
>> reviewing easier.
>
> For me reviewing would be easier when Vasile sends a patchset
> that includes the replacement of tinterlace filter.

The first patch would be quite trivial, this patch is the one you have to
review...

> That way existing fate tests could be used which are fortunately pretty
> extensive in this case.

I thought that one patch should remove the existing filter and
another one adding the new one but I agree that fate suggests
to do this in one patch.

> Also it would be helpful when you and/or other experienced ffmpeg
> developers would clarify first which parts of tinterlace have to be
> rewritten for proper relicensing.

The suggestion is to replace the whole filter instead of rewriting
parts which definitely is the safer solution.

> Being left in the dark makes working on patches frustrating.

I don't understand this comment, sorry.

> Another question is how to deal with vf_interlace? IMHO for the user there
> should be no difference in output, speed and license.

The whole point of this patch is to make a difference license-wise:
Having the same filter also for default compilation is an improvement
imo.

> Two options:
> 1. Relicensing and slice threading will also be ported to vf_interlace

> 2. The commands from vf_interlace will be included in the new tinterlace
> filter. vf_interlace will be deleted together with old tinterlace filter

I believe 2 was suggested. Is the patch not sufficient?

> I would prefer the second option, but maybe there are even better options
> that don´t come to my mind.

Carl Eugen
Thomas Mundt March 7, 2018, 1:04 a.m. UTC | #8
2018-03-07 0:49 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:

> 2018-03-06 19:38 GMT+01:00, Thomas Mundt <tmundt75@gmail.com>:
> >
> > 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
> >
> >> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
> >> > On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
> >> >> Hello,
> >> >>
> >> >> Thanks for the review. I've made changes according to your guidance.
> >> >>
> >> >> It would be great to know if the community will go on with our
> >> >> intention
> >> >> of adding reinterlace as a alternative for tinterlace.
> >> >>
> >> >> That being said, here is the new patch.
> >> >
> >> > As already said, this is not acceptable.
> >> >
> >> > There is no point in having 2 filters with near same funcionality.
> >>
> >> If you consider the new filter ok, the existing filter will be removed
> >> in the same push. I believe sending only the new filter makes
> >> reviewing easier.
> >
> > For me reviewing would be easier when Vasile sends a patchset
> > that includes the replacement of tinterlace filter.
>
> The first patch would be quite trivial, this patch is the one you have to
> review...
>
> > That way existing fate tests could be used which are fortunately pretty
> > extensive in this case.
>
> I thought that one patch should remove the existing filter and
> another one adding the new one but I agree that fate suggests
> to do this in one patch.
>

I would have no problem using fate with two patches - one that removes
vf_tinterlace and another that adds a new vf_tinterlace when they are both
available for the review.
But it seems that Vasile, and to be honest me too, understood your
suggestion that first he shall send a new filter with a different name.
That one shall be reviewed and later on vf_ tinterlace be replaced.

> Also it would be helpful when you and/or other experienced ffmpeg
> > developers would clarify first which parts of tinterlace have to be
> > rewritten for proper relicensing.
>
> The suggestion is to replace the whole filter instead of rewriting
> parts which definitely is the safer solution.
>

Do you mean the whole filter shall be rewritten?
I´m sorry, but I have no clue at what difference from the original, code,
that does the same thing, can be considered as rewritten.


>
> > Being left in the dark makes working on patches frustrating.
>
> I don't understand this comment, sorry.
>

I hope my answer above explains my problem.


>
> > Another question is how to deal with vf_interlace? IMHO for the user
> there
> > should be no difference in output, speed and license.
>
> The whole point of this patch is to make a difference license-wise:
> Having the same filter also for default compilation is an improvement
> imo.
>
> > Two options:
> > 1. Relicensing and slice threading will also be ported to vf_interlace
>
> > 2. The commands from vf_interlace will be included in the new tinterlace
> > filter. vf_interlace will be deleted together with old tinterlace filter
>
> I believe 2 was suggested. Is the patch not sufficient?
>

I didn´t notice that anything was suggested in relation to vf_interlace.
It is not included in the patch and maybe should be separate one.


> > I would prefer the second option, but maybe there are even better options
> > that don´t come to my mind.
>
>
Regards,
Thomas
Vasile Toncu March 13, 2018, 3:10 p.m. UTC | #9
On 06.03.2018 20:38, Thomas Mundt wrote:
> Hi,
>
> 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>
>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>> Hello,
>>>>
>>>> Thanks for the review. I've made changes according to your guidance.
>>>>
>>>> It would be great to know if the community will go on with our intention
>>>> of adding reinterlace as a alternative for tinterlace.
>>>>
>>>> That being said, here is the new patch.
>>> As already said, this is not acceptable.
>>>
>>> There is no point in having 2 filters with near same funcionality.
>> If you consider the new filter ok, the existing filter will be removed
>> in the same push. I believe sending only the new filter makes
>> reviewing easier.
>>
> For me reviewing would be easier when Vasile sends a patchset that includes
> the replacement of tinterlace filter.
> That way existing fate tests could be used which are fortunately pretty
> extensive in this case.
> Also it would be helpful when you and/or other experienced ffmpeg
> developers would clarify first which parts of tinterlace have to be
> rewritten for proper relicensing.
> Being left in the dark makes working on patches frustrating.
>
> Another question is how to deal with vf_interlace? IMHO for the user there
> should be no difference in output, speed and license.
> Two options:
> 1. Relicensing and slice threading will also be ported to vf_interlace
> 2. The commands from vf_interlace will be included in the new tinterlace
> filter. vf_interlace will be deleted together with old tinterlace filter
>
> I would prefer the second option, but maybe there are even better options
> that don´t come to my mind.
>
> Please comment.
> Thanks,
> Thomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Hello everyone,

sorry for a delayed response.

 From what has been discussed in here, I think the reinterlace will 
exist with tinterlace for a period of time, just after that the 
tinterlace can be removed.

To have the reinterlace added, what is needed to be done from my side?

Thanks,
Vasile Toncu

Thanks
Thomas Mundt March 14, 2018, 4:56 p.m. UTC | #10
2018-03-13 16:10 GMT+01:00 Vasile Toncu <vasile.toncu@tremend.com>:

>
>
> On 06.03.2018 20:38, Thomas Mundt wrote:
>
>> Hi,
>>
>> 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>>
>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>>
>>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> Thanks for the review. I've made changes according to your guidance.
>>>>>
>>>>> It would be great to know if the community will go on with our
>>>>> intention
>>>>> of adding reinterlace as a alternative for tinterlace.
>>>>>
>>>>> That being said, here is the new patch.
>>>>>
>>>> As already said, this is not acceptable.
>>>>
>>>> There is no point in having 2 filters with near same funcionality.
>>>>
>>> If you consider the new filter ok, the existing filter will be removed
>>> in the same push. I believe sending only the new filter makes
>>> reviewing easier.
>>>
>>> For me reviewing would be easier when Vasile sends a patchset that
>> includes
>> the replacement of tinterlace filter.
>> That way existing fate tests could be used which are fortunately pretty
>> extensive in this case.
>> Also it would be helpful when you and/or other experienced ffmpeg
>> developers would clarify first which parts of tinterlace have to be
>> rewritten for proper relicensing.
>> Being left in the dark makes working on patches frustrating.
>>
>> Another question is how to deal with vf_interlace? IMHO for the user there
>> should be no difference in output, speed and license.
>> Two options:
>> 1. Relicensing and slice threading will also be ported to vf_interlace
>> 2. The commands from vf_interlace will be included in the new tinterlace
>> filter. vf_interlace will be deleted together with old tinterlace filter
>>
>> I would prefer the second option, but maybe there are even better options
>> that don´t come to my mind.
>>
>> Please comment.
>> Thanks,
>> Thomas
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>
> Hello everyone,
>
> sorry for a delayed response.
>
> From what has been discussed in here, I think the reinterlace will exist
> with tinterlace for a period of time, just after that the tinterlace can be
> removed.
>
> To have the reinterlace added, what is needed to be done from my side?
>
> Thanks,
> Vasile Toncu
>

Two filters with almost the same functionality won´t be accepted, as Paul
stated in this thread.
Also there is vf_interlace filter, which is a subset of vf_tinterlace and
should not differ in speed, output and license. As already said, I would
prefer to include vf_interlace options into vf_tinterlace and remove
vf_interlace.
Also you want several changes: Making tinterlace filter LGPL, adding new
options and adding slice threading.
This should be done in a patch set:

Patch 1/5: Include vf_interlace options into vf_tinterlace filter and
remove vf_interlace
Patch 2/5: Your new LGPL vf_reinterlace filter without the new options,
fixes and slice threading
Patch 3/5: Rename vf_reinterlace and replace vf_tinterlace by it
Patch 4/5: Add slice threading
Patch 5/5: Add the new options and fate tests for them

Please run fate. All tests should pass.
As already said, I don´t have the skills to suggest what has to be done
making the relicensing legal. So I can do a technical review only.
These are just my suggestions to the best of my knowledge! There might be
better ideas from more experienced developers.
Please comment.

Regards,
Thomas
Vasile Toncu March 22, 2018, 1:56 p.m. UTC | #11
On 14.03.2018 18:56, Thomas Mundt wrote:
> 2018-03-13 16:10 GMT+01:00 Vasile Toncu <vasile.toncu@tremend.com>:
>
>>
>> On 06.03.2018 20:38, Thomas Mundt wrote:
>>
>>> Hi,
>>>
>>> 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>>>
>>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> Thanks for the review. I've made changes according to your guidance.
>>>>>>
>>>>>> It would be great to know if the community will go on with our
>>>>>> intention
>>>>>> of adding reinterlace as a alternative for tinterlace.
>>>>>>
>>>>>> That being said, here is the new patch.
>>>>>>
>>>>> As already said, this is not acceptable.
>>>>>
>>>>> There is no point in having 2 filters with near same funcionality.
>>>>>
>>>> If you consider the new filter ok, the existing filter will be removed
>>>> in the same push. I believe sending only the new filter makes
>>>> reviewing easier.
>>>>
>>>> For me reviewing would be easier when Vasile sends a patchset that
>>> includes
>>> the replacement of tinterlace filter.
>>> That way existing fate tests could be used which are fortunately pretty
>>> extensive in this case.
>>> Also it would be helpful when you and/or other experienced ffmpeg
>>> developers would clarify first which parts of tinterlace have to be
>>> rewritten for proper relicensing.
>>> Being left in the dark makes working on patches frustrating.
>>>
>>> Another question is how to deal with vf_interlace? IMHO for the user there
>>> should be no difference in output, speed and license.
>>> Two options:
>>> 1. Relicensing and slice threading will also be ported to vf_interlace
>>> 2. The commands from vf_interlace will be included in the new tinterlace
>>> filter. vf_interlace will be deleted together with old tinterlace filter
>>>
>>> I would prefer the second option, but maybe there are even better options
>>> that don´t come to my mind.
>>>
>>> Please comment.
>>> Thanks,
>>> Thomas
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>> Hello everyone,
>>
>> sorry for a delayed response.
>>
>>  From what has been discussed in here, I think the reinterlace will exist
>> with tinterlace for a period of time, just after that the tinterlace can be
>> removed.
>>
>> To have the reinterlace added, what is needed to be done from my side?
>>
>> Thanks,
>> Vasile Toncu
>>
> Two filters with almost the same functionality won´t be accepted, as Paul
> stated in this thread.
> Also there is vf_interlace filter, which is a subset of vf_tinterlace and
> should not differ in speed, output and license. As already said, I would
> prefer to include vf_interlace options into vf_tinterlace and remove
> vf_interlace.
> Also you want several changes: Making tinterlace filter LGPL, adding new
> options and adding slice threading.
> This should be done in a patch set:
>
> Patch 1/5: Include vf_interlace options into vf_tinterlace filter and
> remove vf_interlace
     Hi,

     From what I've researched, it seems that vf_interlace is just an 
incomplete functionality for vf_tinterlace, so it can be removed directly.

     Can anyone confirm this?

     Regards,
     Vasile Toncu

> Patch 2/5: Your new LGPL vf_reinterlace filter without the new options,
> fixes and slice threading
> Patch 3/5: Rename vf_reinterlace and replace vf_tinterlace by it
> Patch 4/5: Add slice threading
> Patch 5/5: Add the new options and fate tests for them
>
> Please run fate. All tests should pass.
> As already said, I don´t have the skills to suggest what has to be done
> making the relicensing legal. So I can do a technical review only.
> These are just my suggestions to the best of my knowledge! There might be
> better ideas from more experienced developers.
> Please comment.
>
> Regards,
> Thomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Vasile Toncu March 29, 2018, 1:44 p.m. UTC | #12
On 14.03.2018 18:56, Thomas Mundt wrote:
> 2018-03-13 16:10 GMT+01:00 Vasile Toncu <vasile.toncu@tremend.com>:
>
>>
>> On 06.03.2018 20:38, Thomas Mundt wrote:
>>
>>> Hi,
>>>
>>> 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>>>
>>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> Thanks for the review. I've made changes according to your guidance.
>>>>>>
>>>>>> It would be great to know if the community will go on with our
>>>>>> intention
>>>>>> of adding reinterlace as a alternative for tinterlace.
>>>>>>
>>>>>> That being said, here is the new patch.
>>>>>>
>>>>> As already said, this is not acceptable.
>>>>>
>>>>> There is no point in having 2 filters with near same funcionality.
>>>>>
>>>> If you consider the new filter ok, the existing filter will be removed
>>>> in the same push. I believe sending only the new filter makes
>>>> reviewing easier.
>>>>
>>>> For me reviewing would be easier when Vasile sends a patchset that
>>> includes
>>> the replacement of tinterlace filter.
>>> That way existing fate tests could be used which are fortunately pretty
>>> extensive in this case.
>>> Also it would be helpful when you and/or other experienced ffmpeg
>>> developers would clarify first which parts of tinterlace have to be
>>> rewritten for proper relicensing.
>>> Being left in the dark makes working on patches frustrating.
>>>
>>> Another question is how to deal with vf_interlace? IMHO for the user there
>>> should be no difference in output, speed and license.
>>> Two options:
>>> 1. Relicensing and slice threading will also be ported to vf_interlace
>>> 2. The commands from vf_interlace will be included in the new tinterlace
>>> filter. vf_interlace will be deleted together with old tinterlace filter
>>>
>>> I would prefer the second option, but maybe there are even better options
>>> that don´t come to my mind.
>>>
>>> Please comment.
>>> Thanks,
>>> Thomas
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>> Hello everyone,
>>
>> sorry for a delayed response.
>>
>>  From what has been discussed in here, I think the reinterlace will exist
>> with tinterlace for a period of time, just after that the tinterlace can be
>> removed.
>>
>> To have the reinterlace added, what is needed to be done from my side?
>>
>> Thanks,
>> Vasile Toncu
>>
> Two filters with almost the same functionality won´t be accepted, as Paul
> stated in this thread.
> Also there is vf_interlace filter, which is a subset of vf_tinterlace and
> should not differ in speed, output and license. As already said, I would
> prefer to include vf_interlace options into vf_tinterlace and remove
> vf_interlace.
> Also you want several changes: Making tinterlace filter LGPL, adding new
> options and adding slice threading.
> This should be done in a patch set:
>
> Patch 1/5: Include vf_interlace options into vf_tinterlace filter and
> remove vf_interlace

Hello,

Further research I've made showed that vf_tinterlace already contains all
the functionality from vf_interlace. I am ready to start the patches.

Please confirm.

Regards,
Vasile Toncu
> Patch 2/5: Your new LGPL vf_reinterlace filter without the new options,
> fixes and slice threading
> Patch 3/5: Rename vf_reinterlace and replace vf_tinterlace by it
> Patch 4/5: Add slice threading
> Patch 5/5: Add the new options and fate tests for them
>
> Please run fate. All tests should pass.
> As already said, I don´t have the skills to suggest what has to be done
> making the relicensing legal. So I can do a technical review only.
> These are just my suggestions to the best of my knowledge! There might be
> better ideas from more experienced developers.
> Please comment.
>
> Regards,
> Thomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Thomas Mundt March 29, 2018, 3:26 p.m. UTC | #13
2018-03-29 15:44 GMT+02:00 Vasile Toncu <vasile.toncu@tremend.com>:

>
>
> On 14.03.2018 18:56, Thomas Mundt wrote:
>
>> 2018-03-13 16:10 GMT+01:00 Vasile Toncu <vasile.toncu@tremend.com>:
>>
>>
>>> On 06.03.2018 20:38, Thomas Mundt wrote:
>>>
>>> Hi,
>>>>
>>>> 2018-03-05 13:48 GMT+01:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>>>>
>>>> 2018-03-05 12:37 GMT+01:00, Paul B Mahol <onemda@gmail.com>:
>>>>
>>>>> On 3/5/18, Vasile Toncu <vasile.toncu@tremend.com> wrote:
>>>>>>
>>>>>> Hello,
>>>>>>>
>>>>>>> Thanks for the review. I've made changes according to your guidance.
>>>>>>>
>>>>>>> It would be great to know if the community will go on with our
>>>>>>> intention
>>>>>>> of adding reinterlace as a alternative for tinterlace.
>>>>>>>
>>>>>>> That being said, here is the new patch.
>>>>>>>
>>>>>>> As already said, this is not acceptable.
>>>>>>
>>>>>> There is no point in having 2 filters with near same funcionality.
>>>>>>
>>>>>> If you consider the new filter ok, the existing filter will be removed
>>>>> in the same push. I believe sending only the new filter makes
>>>>> reviewing easier.
>>>>>
>>>>> For me reviewing would be easier when Vasile sends a patchset that
>>>>>
>>>> includes
>>>> the replacement of tinterlace filter.
>>>> That way existing fate tests could be used which are fortunately pretty
>>>> extensive in this case.
>>>> Also it would be helpful when you and/or other experienced ffmpeg
>>>> developers would clarify first which parts of tinterlace have to be
>>>> rewritten for proper relicensing.
>>>> Being left in the dark makes working on patches frustrating.
>>>>
>>>> Another question is how to deal with vf_interlace? IMHO for the user
>>>> there
>>>> should be no difference in output, speed and license.
>>>> Two options:
>>>> 1. Relicensing and slice threading will also be ported to vf_interlace
>>>> 2. The commands from vf_interlace will be included in the new tinterlace
>>>> filter. vf_interlace will be deleted together with old tinterlace filter
>>>>
>>>> I would prefer the second option, but maybe there are even better
>>>> options
>>>> that don´t come to my mind.
>>>>
>>>> Please comment.
>>>> Thanks,
>>>> Thomas
>>>> _______________________________________________
>>>> ffmpeg-devel mailing list
>>>> ffmpeg-devel@ffmpeg.org
>>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>>
>>>> Hello everyone,
>>>
>>> sorry for a delayed response.
>>>
>>>  From what has been discussed in here, I think the reinterlace will exist
>>> with tinterlace for a period of time, just after that the tinterlace can
>>> be
>>> removed.
>>>
>>> To have the reinterlace added, what is needed to be done from my side?
>>>
>>> Thanks,
>>> Vasile Toncu
>>>
>>> Two filters with almost the same functionality won´t be accepted, as Paul
>> stated in this thread.
>> Also there is vf_interlace filter, which is a subset of vf_tinterlace and
>> should not differ in speed, output and license. As already said, I would
>> prefer to include vf_interlace options into vf_tinterlace and remove
>> vf_interlace.
>> Also you want several changes: Making tinterlace filter LGPL, adding new
>> options and adding slice threading.
>> This should be done in a patch set:
>>
>> Patch 1/5: Include vf_interlace options into vf_tinterlace filter and
>> remove vf_interlace
>>
>
> Hello,
>
> Further research I've made showed that vf_tinterlace already contains all
> the functionality from vf_interlace. I am ready to start the patches.
>
> Please confirm.
>

The functionality is not the point. The options must not be removed.
"ffmpeg -i input vf interlace output" must remain for the user.


> Regards,
> Vasile Toncu
>
>> Patch 2/5: Your new LGPL vf_reinterlace filter without the new options,
>> fixes and slice threading
>> Patch 3/5: Rename vf_reinterlace and replace vf_tinterlace by it
>> Patch 4/5: Add slice threading
>> Patch 5/5: Add the new options and fate tests for them
>>
>> Please run fate. All tests should pass.
>> As already said, I don´t have the skills to suggest what has to be done
>> making the relicensing legal. So I can do a technical review only.
>> These are just my suggestions to the best of my knowledge! There might be
>> better ideas from more experienced developers.
>> Please comment.
>>
>> Regards,
>> Thomas
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
diff mbox

Patch

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 6a60836..c3095ba 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -286,6 +286,7 @@  OBJS-$(CONFIG_RANDOM_FILTER) += vf_random.o
  OBJS-$(CONFIG_READEIA608_FILTER)             += vf_readeia608.o
  OBJS-$(CONFIG_READVITC_FILTER)               += vf_readvitc.o
  OBJS-$(CONFIG_REALTIME_FILTER)               += f_realtime.o
+OBJS-$(CONFIG_REINTERLACE_FILTER)            += vf_reinterlace.o
  OBJS-$(CONFIG_REMAP_FILTER)                  += vf_remap.o framesync.o
  OBJS-$(CONFIG_REMOVEGRAIN_FILTER)            += vf_removegrain.o
  OBJS-$(CONFIG_REMOVELOGO_FILTER)             += bbox.o lswsutils.o 
lavfutils.o vf_removelogo.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 9adb109..60fb9b5 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -295,6 +295,7 @@  static void register_all(void)
      REGISTER_FILTER(READEIA608,     readeia608,     vf);
      REGISTER_FILTER(READVITC,       readvitc,       vf);
      REGISTER_FILTER(REALTIME,       realtime,       vf);
+    REGISTER_FILTER(REINTERLACE,    reinterlace,    vf);
      REGISTER_FILTER(REMAP,          remap,          vf);
      REGISTER_FILTER(REMOVEGRAIN,    removegrain,    vf);
      REGISTER_FILTER(REMOVELOGO,     removelogo,     vf);
diff --git a/libavfilter/reinterlace.h b/libavfilter/reinterlace.h
new file mode 100644
index 0000000..3413a7e
--- /dev/null
+++ b/libavfilter/reinterlace.h
@@ -0,0 +1,141 @@ 
+/*
+ * Copyright (c) 2017 Vasile Toncu <toncuvasile@gmail.com>
+ * Copyright (c) 2017 Thomas Mundt <tmundt75@gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
02110-1301 USA
+ */
+
+#include <stdint.h>
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+#include "libavutil/avassert.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+#include "libavutil/bswap.h"
+
+enum FilterMode {
+    MODE_MERGE,
+    MODE_DROP_EVEN,
+    MODE_DROP_ODD,
+    MODE_PAD,
+    MODE_INTERLEAVE_TOP,
+    MODE_INTERLEAVE_BOTTOM,
+    MODE_INTERLACE_X2,
+    MODE_MERGE_X2,
+    MODE_MERGE_TFF,
+    MODE_MERGE_BFF,
+    MODE_NB
+};
+
+enum FilterFlags {
+    FLAG_NOTHING    = 0x00,
+    FLAG_VLPF       = 0x01,
+    FLAG_EXACT_TB   = 0x02,
+    FLAG_CVLPF      = 0x04,
+    FLAG_NB
+};
+
+static const AVRational standard_tbs[] = {
+    {1, 25},
+    {1, 30},
+    {1001, 30000},
+};
+
+typedef struct {
+    const AVClass *class;
+    int mode;
+    int flags;
+
+    AVFrame *prev_frame, *current_frame;
+    int64_t current_frame_index;
+
+    void *black_vec[4];
+
+    int skip_next_frame;
+
+    void *thread_data;
+
+    uint8_t bit_depth;
+
+    void (*lowpass_line)(uint8_t *dstp, ptrdiff_t width, const uint8_t 
*srcp,
+                         ptrdiff_t mref, ptrdiff_t pref, int clip_max);
+
+    AVRational preout_time_base;
+
+} ReInterlaceContext;
+
+#if CONFIG_GPL
+void ff_reinterlace_init_x86(ReInterlaceContext *reinterlace);
+#endif
+
+#define OFFSET(x) offsetof(ReInterlaceContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+
+static const AVOption reinterlace_options[] = {
+    { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, 
{.i64=MODE_MERGE},     0, MODE_NB - 1, FLAGS, "mode" },
+    { "merge",             "merge frames",                0, 
AV_OPT_TYPE_CONST, {.i64=MODE_MERGE},                INT_MIN, INT_MAX, 
FLAGS, "mode"},
+    { "drop_even",         "drop even frames",            0, 
AV_OPT_TYPE_CONST, {.i64=MODE_DROP_EVEN},            INT_MIN, INT_MAX, 
FLAGS, "mode"},
+    { "drop_odd",          "drop odd frames",             0, 
AV_OPT_TYPE_CONST, {.i64=MODE_DROP_ODD},             INT_MIN, INT_MAX, 
FLAGS, "mode"},
+    { "pad",               "pad lines of a frame with black 
lines",                  0, AV_OPT_TYPE_CONST, 
{.i64=MODE_PAD},                  INT_MIN, INT_MAX, FLAGS, "mode"},
+    { "interleave_top",    "interleave top and bottom frames",       0, 
AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_TOP},       INT_MIN, INT_MAX, 
FLAGS, "mode"},
+    { "interleave_bottom", "interleave bottom and top frames", 0, 
AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_BOTTOM},    INT_MIN, INT_MAX, 
FLAGS, "mode"},
+    { "interlacex2",       "interlace consecutive frames",         0, 
AV_OPT_TYPE_CONST, {.i64=MODE_INTERLACE_X2},         INT_MIN, INT_MAX, 
FLAGS, "mode"},
+    { "mergex2",           "just like merge, but at the same frame 
rate",             0, AV_OPT_TYPE_CONST, 
{.i64=MODE_MERGE_X2},             INT_MIN, INT_MAX, FLAGS, "mode"},
+    { "merge_tff",         "merge frames using top_field_first 
information",            0, AV_OPT_TYPE_CONST, 
{.i64=MODE_MERGE_TFF},            INT_MIN, INT_MAX, FLAGS, "mode"},
+    { "merge_bff",         "Mmerge frames using top_field_first 
information",            0, AV_OPT_TYPE_CONST, 
{.i64=MODE_MERGE_BFF},            INT_MIN, INT_MAX, FLAGS, "mode"},
+
+    { "flags", "add flag for reinterlace", OFFSET(flags), 
AV_OPT_TYPE_INT, {.i64=FLAG_NOTHING}, 0, 0xFF, FLAGS, "flags" },
+    { "low_pass_filter",   "low pass fitler",                 0, 
AV_OPT_TYPE_CONST, {.i64 = FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags"},
+    { "vlpf",              "low pass filter",                 0, 
AV_OPT_TYPE_CONST, {.i64 = FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags"},
+    { "complex_filter",    "enable complex vertical low-pass 
filter",      0, AV_OPT_TYPE_CONST, {.i64 = FLAG_CVLPF},INT_MIN, 
INT_MAX, FLAGS, "flags" },
+    { "cvlpf",             "enable complex vertical low-pass 
filter",      0, AV_OPT_TYPE_CONST, {.i64 = FLAG_CVLPF},INT_MIN, 
INT_MAX, FLAGS, "flags" },
+    { "exact_tb",          "force a timebase which can represent 
timestamps exactly", 0, AV_OPT_TYPE_CONST, {.i64 = FLAG_EXACT_TB}, 
INT_MIN, INT_MAX, FLAGS, "flags" },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(reinterlace);
+
+#define IS_ODD(value) (value & 1)
+
+typedef struct ReInterlaceThreadData {
+    AVFrame *out, *first, *second;
+    int plane;
+    ReInterlaceContext *reinterlace;
+
+    int scale_w_plane12_factor;
+    int scale_h_plane12_factor;
+
+} ReInterlaceThreadData;
+
+static enum AVPixelFormat all_pix_fmts[] = {
+        AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
+        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
+        AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
+        AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUV422P10LE,
+        AV_PIX_FMT_YUV440P10LE, AV_PIX_FMT_YUV444P10LE,
+        AV_PIX_FMT_YUV420P12LE, AV_PIX_FMT_YUV422P12LE,
+        AV_PIX_FMT_YUV440P12LE, AV_PIX_FMT_YUV444P12LE,
+        AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
+        AV_PIX_FMT_YUVA420P10LE, AV_PIX_FMT_YUVA422P10LE, 
AV_PIX_FMT_YUVA444P10LE,
+        AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, 
AV_PIX_FMT_YUVJ440P,
+        AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
+};
diff --git a/libavfilter/vf_reinterlace.c b/libavfilter/vf_reinterlace.c
new file mode 100644
index 0000000..35f8e02
--- /dev/null
+++ b/libavfilter/vf_reinterlace.c
@@ -0,0 +1,757 @@ 
+/*
+ * Copyright (c) 2018 Vasile Toncu <toncuvasile@gmail.com>
+ * Copyright (c) 2017 Thomas Mundt <tmundt75@gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
02110-1301 USA
+ */
+
+/**
+ * @file
+ * Reinterlace filter
+ */
+
+
+#include "reinterlace.h"
+
+
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    ReInterlaceContext *reinterlace = ctx->priv;
+    int i;
+
+    for (i = 0; i < 4; i++)
+        reinterlace->black_vec[i] = NULL;
+
+    reinterlace->thread_data = av_malloc(4 * 
sizeof(ReInterlaceThreadData));
+
+    return 0;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+
+    AVFilterFormats *fmts_list;
+
+    fmts_list = ff_make_format_list(all_pix_fmts);
+
+    if (!fmts_list)
+        return AVERROR(ENOMEM);
+
+    return ff_set_common_formats(ctx, fmts_list);
+}
+
+static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const 
uint8_t *srcp,
+                           ptrdiff_t mref, ptrdiff_t pref, int clip_max)
+{
+    const uint8_t *srcp_above = srcp + mref;
+    const uint8_t *srcp_below = srcp + pref;
+    int i;
+    for (i = 0; i < width; i++) {
+        // this calculation is an integer representation of
+        // '0.5 * current + 0.25 * above + 0.25 * below'
+        // '1 +' is for rounding.
+        dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + 
srcp_below[i]) >> 2;
+    }
+}
+
+static void lowpass_line_c_16(uint8_t *dst8, ptrdiff_t width, const 
uint8_t *src8,
+                              ptrdiff_t mref, ptrdiff_t pref, int clip_max)
+{
+    uint16_t *dstp = (uint16_t *)dst8;
+    const uint16_t *srcp = (const uint16_t *)src8;
+    const uint16_t *srcp_above = srcp + mref / 2;
+    const uint16_t *srcp_below = srcp + pref / 2;
+    int i, src_x;
+    for (i = 0; i < width; i++) {
+        // this calculation is an integer representation of
+        // '0.5 * current + 0.25 * above + 0.25 * below'
+        // '1 +' is for rounding.
+        src_x   = av_le2ne16(srcp[i]) << 1;
+        dstp[i] = av_le2ne16((1 + src_x + av_le2ne16(srcp_above[i])
+                             + av_le2ne16(srcp_below[i])) >> 2);
+    }
+}
+
+static void lowpass_line_complex_c(uint8_t *dstp, ptrdiff_t width, 
const uint8_t *srcp,
+                                   ptrdiff_t mref, ptrdiff_t pref, int 
clip_max)
+{
+    const uint8_t *srcp_above = srcp + mref;
+    const uint8_t *srcp_below = srcp + pref;
+    const uint8_t *srcp_above2 = srcp + mref * 2;
+    const uint8_t *srcp_below2 = srcp + pref * 2;
+    int i, src_x, src_ab;
+    for (i = 0; i < width; i++) {
+        // this calculation is an integer representation of
+        // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * 
above2 - 0.125 * below2'
+        // '4 +' is for rounding.
+        src_x   = srcp[i] << 1;
+        src_ab  = srcp_above[i] + srcp_below[i];
+        dstp[i] = av_clip_uint8((4 + ((srcp[i] + src_x + src_ab) << 1)
+                                - srcp_above2[i] - srcp_below2[i]) >> 3);
+        // Prevent over-sharpening:
+        // dst must not exceed src when the average of above and below
+        // is less than src. And the other way around.
+        if (src_ab > src_x) {
+            if (dstp[i] < srcp[i])
+                dstp[i] = srcp[i];
+        } else if (dstp[i] > srcp[i])
+            dstp[i] = srcp[i];
+    }
+}
+
+static void lowpass_line_complex_c_16(uint8_t *dst8, ptrdiff_t width, 
const uint8_t *src8,
+                                      ptrdiff_t mref, ptrdiff_t pref, 
int clip_max)
+{
+    uint16_t *dstp = (uint16_t *)dst8;
+    const uint16_t *srcp = (const uint16_t *)src8;
+    const uint16_t *srcp_above = srcp + mref / 2;
+    const uint16_t *srcp_below = srcp + pref / 2;
+    const uint16_t *srcp_above2 = srcp + mref;
+    const uint16_t *srcp_below2 = srcp + pref;
+    int i, dst_le, src_le, src_x, src_ab;
+    for (i = 0; i < width; i++) {
+        // this calculation is an integer representation of
+        // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * 
above2 - 0.125 * below2'
+        // '4 +' is for rounding.
+        src_le = av_le2ne16(srcp[i]);
+        src_x  = src_le << 1;
+        src_ab = av_le2ne16(srcp_above[i]) + av_le2ne16(srcp_below[i]);
+        dst_le = av_clip((4 + ((src_le + src_x + src_ab) << 1)
+                         - av_le2ne16(srcp_above2[i])
+                         - av_le2ne16(srcp_below2[i])) >> 3, 0, clip_max);
+        // Prevent over-sharpening:
+        // dst must not exceed src when the average of above and below
+        // is less than src. And the other way around.
+        if (src_ab > src_x) {
+            if (dst_le < src_le)
+                dstp[i] = av_le2ne16(src_le);
+            else
+                dstp[i] = av_le2ne16(dst_le);
+        } else if (dst_le > src_le) {
+            dstp[i] = av_le2ne16(src_le);
+        } else
+            dstp[i] = av_le2ne16(dst_le);
+    }
+}
+
+/**
+ * alocate memory for a black frame
+ */
+static int init_black_buffers(ReInterlaceContext *reinterlace, 
AVFilterLink *inlink, int format)
+{
+    int black_vec_size = inlink->w * inlink->h * 3 * ( 
(reinterlace->bit_depth > 8) ? 2 : 1 );
+    int val_black = 16;
+    int i;
+
+    if (format == AV_PIX_FMT_YUVJ420P ||
+        format == AV_PIX_FMT_YUVJ422P ||
+        format == AV_PIX_FMT_YUVJ440P ||
+        format == AV_PIX_FMT_YUVJ444P) {
+
+        val_black = 0;
+
+    }
+
+    for (i = 0; i < 4; i++) {
+        if (reinterlace->bit_depth > 8) {
+            reinterlace->black_vec[i] = (uint16_t *) 
av_malloc(black_vec_size);
+        } else {
+            reinterlace->black_vec[i] = (uint8_t *) 
av_malloc(black_vec_size);
+        }
+
+
+        if (!reinterlace->black_vec[i] )
+            return AVERROR(ENOMEM);
+
+        if (reinterlace->bit_depth > 8) {
+            memset( (uint16_t) reinterlace->black_vec[i], (i == 0 || i 
== 3 ? val_black : 128),  black_vec_size);
+        } else {
+            memset( (uint8_t) reinterlace->black_vec[i], (i == 0 || i 
== 3 ? val_black : 128),  black_vec_size);
+        }
+
+    }
+
+    return 0;
+}
+
+static int config_out_props(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = outlink->src->inputs[0];
+    ReInterlaceContext *reinterlace = ctx->priv;
+    const AVPixFmtDescriptor *fmt_desc = 
av_pix_fmt_desc_get(outlink->format);
+    int reinterlace_mode = reinterlace->mode;
+    int ret;
+
+    reinterlace->bit_depth = fmt_desc->comp[0].depth;
+    reinterlace->preout_time_base = inlink->time_base;
+
+    switch (reinterlace_mode) {
+    case MODE_PAD:
+        outlink->w = inlink->w;
+        outlink->h = 2 * inlink->h;
+        outlink->sample_aspect_ratio = 
av_mul_q(inlink->sample_aspect_ratio, av_make_q(2, 1));
+
+        ret = init_black_buffers(reinterlace, inlink, outlink->format);
+
+        if (ret < 0)
+           return ret;
+
+    break;
+
+    case MODE_DROP_EVEN:
+    case MODE_DROP_ODD:
+        outlink->w = inlink->w;
+        outlink->h = inlink->h;
+        outlink->frame_rate = av_mul_q(inlink->frame_rate, 
(AVRational){1,2});
+        outlink->time_base  = av_mul_q(inlink->time_base , 
(AVRational){2,1});
+        break;
+
+    case MODE_INTERLEAVE_TOP:
+    case MODE_INTERLEAVE_BOTTOM:
+        outlink->w = inlink->w;
+        outlink->h = inlink->h;
+        outlink->frame_rate = av_mul_q(inlink->frame_rate, 
(AVRational){1,2});
+        outlink->time_base  = av_mul_q(inlink->time_base , 
(AVRational){2,1});
+        break;
+
+    case MODE_INTERLACE_X2:
+        outlink->w = inlink->w;
+        outlink->h = inlink->h;
+        reinterlace->preout_time_base.den *= 2;
+        outlink->frame_rate = av_mul_q(inlink->frame_rate, 
(AVRational){2,1});
+        outlink->time_base  = av_mul_q(inlink->time_base , 
(AVRational){1,2});
+        break;
+
+    case MODE_MERGE_X2:
+        outlink->w = inlink->w;
+        outlink->h = 2 * inlink->h;
+        outlink->sample_aspect_ratio = 
av_mul_q(inlink->sample_aspect_ratio, av_make_q(2, 1));
+        outlink->frame_rate = inlink->frame_rate;
+        outlink->time_base  = inlink->time_base;
+        break;
+
+    case MODE_MERGE:
+    case MODE_MERGE_BFF:
+    case MODE_MERGE_TFF:
+        outlink->w = inlink->w;
+        outlink->h = 2 * inlink->h;
+        outlink->sample_aspect_ratio = 
av_mul_q(inlink->sample_aspect_ratio, av_make_q(2, 1));
+        outlink->frame_rate = av_mul_q(inlink->frame_rate, 
(AVRational){1,2});
+        outlink->time_base  = av_mul_q(inlink->time_base , 
(AVRational){2,1});
+        break;
+
+    default:
+        av_log(ctx, AV_LOG_VERBOSE, "invalid value for mode");
+        av_assert0(0);
+
+    }
+
+    int i;
+    for (i = 0; i < FF_ARRAY_ELEMS(standard_tbs); i++) {
+        if (!av_cmp_q(standard_tbs[i], outlink->time_base))
+            break;
+    }
+    if (i == FF_ARRAY_ELEMS(standard_tbs) || (reinterlace->flags & 
FLAG_EXACT_TB) )
+        outlink->time_base = reinterlace->preout_time_base;
+
+
+    if (reinterlace->flags & FLAG_VLPF || reinterlace->flags & 
FLAG_CVLPF) {
+
+        if (reinterlace_mode != MODE_INTERLEAVE_TOP && reinterlace_mode 
!= MODE_INTERLEAVE_BOTTOM) {
+            reinterlace->flags &= ~(FLAG_VLPF | FLAG_CVLPF);
+        } else {
+            reinterlace->lowpass_line = (reinterlace->flags & 
FLAG_VLPF) ? lowpass_line_c : lowpass_line_complex_c;
+
+            if (reinterlace->bit_depth > 8) {
+                reinterlace->lowpass_line = (reinterlace->flags & 
FLAG_VLPF) ? lowpass_line_c_16 : lowpass_line_complex_c_16;
+            }
+
+#if CONFIG_GPL
+            if (ARCH_X86) {
+                ff_reinterlace_init_x86(reinterlace);
+            }
+#endif
+        }
+
+    }
+
+    return 0;
+}
+
+static int filter_frame_plane(AVFilterContext *ctx, void *arg, int 
jobnr, int nb_jobs)
+{
+    // jobnr is usualy plane number
+    ReInterlaceThreadData *rtd = arg;
+    ReInterlaceContext *reinterlace = rtd->reinterlace;
+    AVFrame *first = rtd->first;
+    AVFrame *second = rtd->second;
+    AVFrame *out = rtd->out;
+
+    int plane = rtd->plane;
+    int reinterlace_mode = reinterlace->mode;
+
+    int x = (plane == 1 || plane == 2) ? rtd->scale_w_plane12_factor : 1;
+    int y = (plane == 1 || plane == 2) ? rtd->scale_h_plane12_factor : 1;
+    int i, ls_offset;
+    int offset1, offset2, offset3, offset4;
+
+    const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(out->format);
+    int clip_max = (1 << fmt_desc->comp[plane].depth) - 1;
+
+    switch (reinterlace_mode) {
+    case MODE_MERGE:
+        av_image_copy_plane(out->data[plane], 2 * out->linesize[plane],
+            first->data[plane], first->linesize[plane], first->width / 
x, first->height / y);
+        av_image_copy_plane(out->data[plane] + out->linesize[plane], 2 
* out->linesize[plane],
+            second->data[plane], second->linesize[plane], second->width 
/ x, second->height / y);
+        break;
+
+    case MODE_PAD:
+        ls_offset = (reinterlace->current_frame_index & 1) ? 0 : 
out->linesize[plane];
+        av_image_copy_plane(out->data[plane] + ls_offset, 2 * 
out->linesize[plane],
+            second->data[plane], second->linesize[plane], second->width 
/ x, second->height / y);
+        av_image_copy_plane(out->data[plane] + out->linesize[plane] - 
ls_offset, 2 * out->linesize[plane],
+            reinterlace->black_vec[plane], second->linesize[plane], 
second->width / x, second->height / y);
+        break;
+
+    case MODE_INTERLEAVE_BOTTOM:
+    case MODE_INTERLEAVE_TOP:
+        y = y * 2;
+
+        if (reinterlace->flags & FLAG_VLPF || reinterlace->flags & 
FLAG_CVLPF) {
+
+            int lines, cols;
+            AVFrame *from_frame;
+            uint8_t *from, *to;
+            int from_step, to_step;
+
+            lines = (reinterlace_mode == MODE_INTERLEAVE_TOP) ? (2 * 
out->height / y + 1) / 2 : (2 * out->height / y + 0) / 2;
+            cols = out->width / x;
+            from_frame = first;
+            from = from_frame->data[plane];
+            to = out->data[plane];
+
+            if (reinterlace_mode == MODE_INTERLEAVE_BOTTOM) {
+                from = from + from_frame->linesize[plane];
+                to = to + out->linesize[plane];
+            }
+
+            from_step = 2 * from_frame->linesize[plane];
+            to_step = 2 * out->linesize[plane];
+
+            // when i = lines - aka first line
+            reinterlace->lowpass_line(to, cols, from, 
from_frame->linesize[plane], 0, clip_max);
+            to += to_step;
+            from += from_step;
+
+            int cvlfp = !!(reinterlace->flags & FLAG_CVLPF);
+            if (cvlfp) {
+                reinterlace->lowpass_line(to, cols, from, 
from_frame->linesize[plane], 0, clip_max);
+                to += to_step;
+                from += from_step;
+            }
+
+            for (i = lines - 2 - 2 * cvlfp; i; i--) {
+                reinterlace->lowpass_line(to, cols, from, 
from_frame->linesize[plane], -from_frame->linesize[plane], clip_max);
+                to += to_step;
+                from += from_step;
+            }
+
+            // when i == 1 - aka last line
+            reinterlace->lowpass_line(to, cols, from, 0, 
-from_frame->linesize[plane], clip_max);
+            to += to_step;
+            from += from_step;
+
+            if (cvlfp) {
+                reinterlace->lowpass_line(to, cols, from, 0, 
-from_frame->linesize[plane], clip_max);
+                to += to_step;
+                from += from_step;
+            }
+
+
+            lines = (reinterlace_mode == MODE_INTERLEAVE_BOTTOM) ? ((2 
* out->height / y) + 1) / 2 : (2 * out->height / y + 0) / 2;
+            cols = out->width / x;
+            from_frame = second;
+            from = from_frame->data[plane];
+            to = out->data[plane];
+
+            if (reinterlace_mode == MODE_INTERLEAVE_TOP) {
+                from = from + from_frame->linesize[plane];
+                to = to + out->linesize[plane];
+            }
+
+            from_step = 2 * from_frame->linesize[plane];
+            to_step = 2 * out->linesize[plane];
+
+            // when i = lines
+            reinterlace->lowpass_line(to, cols, from, 
from_frame->linesize[plane], 0, clip_max);
+            to += to_step;
+            from += from_step;
+
+            if (cvlfp) {
+                reinterlace->lowpass_line(to, cols, from, 
from_frame->linesize[plane], 0, clip_max);
+                to += to_step;
+                from += from_step;
+            }
+
+
+            for (i = lines - 2 - 2 * cvlfp; i; i--) {
+                reinterlace->lowpass_line(to, cols, from, 
from_frame->linesize[plane], -from_frame->linesize[plane], clip_max);
+                to += to_step;
+                from += from_step;
+            }
+
+            // when i == 1
+            reinterlace->lowpass_line(to, cols, from, 0, 
-from_frame->linesize[plane], clip_max);
+            to += to_step;
+            from += from_step;
+
+            if (cvlfp) {
+                reinterlace->lowpass_line(to, cols, from, 0, 
-from_frame->linesize[plane], clip_max);
+                to += to_step;
+                from += from_step;
+            }
+
+        } else {
+            offset1 = (reinterlace_mode == MODE_INTERLEAVE_TOP) ? 0 : 
out->linesize[plane];
+            offset2 = (reinterlace_mode == MODE_INTERLEAVE_TOP) ? 0 : 
first->linesize[plane];
+            offset3 = (reinterlace_mode == MODE_INTERLEAVE_TOP) ? 
out->linesize[plane]    : 0;
+            offset4 = (reinterlace_mode == MODE_INTERLEAVE_TOP) ? 
second->linesize[plane] : 0;
+
+            av_image_copy_plane(out->data[plane] + offset1, 2 * 
out->linesize[plane],
+                first->data[plane] + offset2, 2 * first->linesize[plane],
+                first->width / x, first->height / y);
+            av_image_copy_plane(out->data[plane] + offset3, 2 * 
out->linesize[plane],
+                second->data[plane] + offset4, 2 * 
second->linesize[plane],
+                second->width / x, second->height / y);
+        }
+        break;
+
+    case MODE_INTERLACE_X2:
+        y = y * 2;
+
+        offset1 = 0; offset2 = 0;
+        offset3 = out->linesize[plane];
+        offset4 = second->linesize[plane];
+
+        if (second->interlaced_frame && second->top_field_first) {
+            offset1 = out->linesize[plane];
+            offset2 = first->linesize[plane];
+            offset3 = 0; offset4 = 0;
+        }
+
+        av_image_copy_plane(out->data[plane] + offset1, 2 * 
out->linesize[plane],
+            first->data[plane] + offset2, 2 * first->linesize[plane],
+            first->width / x, first->height / y);
+        av_image_copy_plane(out->data[plane] + offset3, 2 * 
out->linesize[plane],
+            second->data[plane] + offset4, 2 * second->linesize[plane],
+            second->width / x, second->height / y);
+        break;
+
+    case MODE_MERGE_X2:
+        if (IS_ODD(reinterlace->current_frame_index - 1)) {
+            av_image_copy_plane(out->data[plane], 2 * 
out->linesize[plane],
+                second->data[plane], second->linesize[plane], 
second->width / x, second->height / y);
+            av_image_copy_plane(out->data[plane] + 
out->linesize[plane], 2 * out->linesize[plane],
+                first->data[plane], first->linesize[plane], 
first->width / x, first->height / y);
+        } else {
+            av_image_copy_plane(out->data[plane], 2 * 
out->linesize[plane],
+                first->data[plane], first->linesize[plane], 
first->width / x, first->height / y);
+            av_image_copy_plane(out->data[plane] + 
out->linesize[plane], 2 * out->linesize[plane],
+                second->data[plane], second->linesize[plane], 
second->width / x, second->height / y);
+        }
+        break;
+
+    case MODE_MERGE_TFF:
+    case MODE_MERGE_BFF:
+        offset1 = (reinterlace_mode == MODE_MERGE_TFF) ? 0 : 
out->linesize[plane];
+        offset2 = (reinterlace_mode == MODE_MERGE_TFF) ? 
out->linesize[plane] : 0;
+
+        av_image_copy_plane(out->data[plane] + offset1, 2 * 
out->linesize[plane],
+            first->data[plane], first->linesize[plane], first->width / 
x, first->height / y);
+        av_image_copy_plane(out->data[plane] + offset2, 2 * 
out->linesize[plane],
+            second->data[plane], second->linesize[plane], second->width 
/ x, second->height / y);
+        break;
+
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static ReInterlaceThreadData *get_ReInterlaceThreadData(AVFrame *out, 
AVFrame *first, AVFrame *second,
+                int plane, ReInterlaceContext *reinterlace,
+                int scale_w_plane12_factor,
+                int scale_h_plane12_factor)
+{
+    ReInterlaceThreadData *rtd = &((ReInterlaceThreadData 
*)reinterlace->thread_data)[plane];
+
+    if (!rtd)
+        return rtd;
+
+    rtd->out = out;
+    rtd->first = first;
+    rtd->second = second;
+    rtd->plane = plane;
+    rtd->reinterlace = reinterlace;
+    rtd->scale_h_plane12_factor = scale_h_plane12_factor;
+    rtd->scale_w_plane12_factor = scale_w_plane12_factor;
+
+    return rtd;
+}
+
+static void copy_all_planes(AVFilterContext *ctx,
+    ReInterlaceContext *reinterlace,
+    const AVPixFmtDescriptor *desc,
+    AVFrame *out, AVFrame *first, AVFrame *second)
+{
+    int scale_w_plane12_factor = 1 << desc->log2_chroma_w;
+    int scale_h_plane12_factor = 1 << desc->log2_chroma_h;
+    int plane;
+
+    for (plane = 0; plane < desc->nb_components; plane++) {
+
+        ReInterlaceThreadData *rtd = get_ReInterlaceThreadData(out, 
first, second,
+            plane, reinterlace, scale_w_plane12_factor, 
scale_h_plane12_factor);
+
+        //ctx->internal->execute(ctx, filter_frame_plane, rtd, NULL, 
FFMIN(desc->nb_components, ctx->graph->nb_threads));
+        filter_frame_plane(ctx, rtd, plane, desc->nb_components);
+    }
+}
+
+
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx            = inlink->dst;
+    ReInterlaceContext *reinterlace = ctx->priv;
+    AVFilterLink *outlink           = ctx->outputs[0];
+    const AVPixFmtDescriptor *desc  = av_pix_fmt_desc_get(outlink->format);
+    AVFrame *out, *first, *second;
+    int ret;
+
+    int reinterlace_mode = reinterlace->mode;
+
+    av_frame_free(&(reinterlace->prev_frame));
+    reinterlace->prev_frame = reinterlace->current_frame;
+    reinterlace->current_frame = in;
+    reinterlace->current_frame_index++;
+
+    // we process two frames at a time, thus only even frame indexes 
are considered
+    if (IS_ODD(reinterlace->current_frame_index)) {
+        if (reinterlace_mode == MODE_PAD || reinterlace_mode == 
MODE_MERGE_X2
+            || reinterlace_mode == MODE_INTERLACE_X2 || 
reinterlace_mode == MODE_MERGE_BFF
+            || reinterlace_mode == MODE_MERGE_TFF) {
+            // continue
+        } else {
+            return 0;
+        }
+    }
+
+    first   = reinterlace->prev_frame;
+    second  = reinterlace->current_frame;
+
+    switch (reinterlace_mode) {
+    case MODE_DROP_EVEN:
+    case MODE_DROP_ODD:
+        out = (reinterlace_mode == MODE_DROP_ODD) ? 
reinterlace->current_frame : reinterlace->prev_frame;
+        out = av_frame_clone(out);
+
+        if (!out)
+            return AVERROR(ENOMEM);
+
+        //out->pts = out->pts >> 1;
+        out->pts = av_rescale_q(out->pts, 
reinterlace->preout_time_base, outlink->time_base);
+        ret = ff_filter_frame(outlink, out);
+        break;
+
+    case MODE_MERGE:
+    case MODE_MERGE_X2:
+    case MODE_MERGE_TFF:
+    case MODE_MERGE_BFF:
+        if (reinterlace_mode == MODE_MERGE_X2 && 
reinterlace->current_frame_index == 1)
+            return 0;
+
+        if (reinterlace_mode == MODE_MERGE_BFF || reinterlace_mode == 
MODE_MERGE_TFF) {
+           if (!first)
+                return 0;
+
+            if (reinterlace->skip_next_frame) {
+                reinterlace->skip_next_frame = 0;
+                return 0;
+            }
+
+            if (first->interlaced_frame == 1 && 
second->interlaced_frame == 1)
+            {
+                if (first->top_field_first == second->top_field_first)
+                    return 0;
+                else if (reinterlace->mode == MODE_MERGE_BFF && 
first->top_field_first != 0)
+                    return 0;
+                else if (reinterlace->mode == MODE_MERGE_TFF && 
first->top_field_first != 1)
+                    return 0;
+            }
+        }
+
+        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+
+        if (!out)
+            return AVERROR(ENOMEM);
+
+        av_frame_copy_props(out, first);
+        out->sample_aspect_ratio    = 
av_mul_q(first->sample_aspect_ratio, av_make_q(2, 1));
+        out->interlaced_frame       = 1;
+        out->top_field_first        = reinterlace_mode == 
MODE_MERGE_BFF ? 0 : 1;
+        out->height                 = outlink->h;
+
+        //if (MODE_MERGE == reinterlace_mode)
+        //    out->pts = out->pts >> 1;
+
+        copy_all_planes(ctx, reinterlace, desc, out, first, second);
+
+        if (reinterlace_mode == MODE_MERGE_BFF || reinterlace_mode == 
MODE_MERGE_TFF)
+            reinterlace->skip_next_frame = 1;
+
+        out->pts = av_rescale_q(out->pts, 
reinterlace->preout_time_base, outlink->time_base);
+        ret = ff_filter_frame(outlink, out);
+        break;
+
+    case MODE_PAD:
+        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+
+        if (!out)
+            return AVERROR(ENOMEM);
+
+        av_frame_copy_props(out, second);
+        out->sample_aspect_ratio = 
av_mul_q(second->sample_aspect_ratio, av_make_q(2, 1));
+        out->height = outlink->h;
+
+        copy_all_planes(ctx, reinterlace, desc, out, first, second);
+
+        out->pts = av_rescale_q(out->pts, 
reinterlace->preout_time_base, outlink->time_base);
+        ret = ff_filter_frame(outlink, out);
+        break;
+
+    case MODE_INTERLEAVE_BOTTOM:
+    case MODE_INTERLEAVE_TOP:
+        out  = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+
+        if (!out)
+            return AVERROR(ENOMEM);
+
+        av_frame_copy_props(out, first);
+
+        copy_all_planes(ctx, reinterlace, desc, out, first, second);
+
+        //out->pts = out->pts >> 1;
+        out->interlaced_frame = 1;
+        out->top_field_first = (reinterlace_mode == 
MODE_INTERLEAVE_TOP) ? 1 : 0;
+
+        out->pts = av_rescale_q(out->pts, 
reinterlace->preout_time_base, outlink->time_base);
+        ret = ff_filter_frame(outlink, out);
+        break;
+
+    case MODE_INTERLACE_X2:
+        if (reinterlace->current_frame_index == 1)
+            return 0;
+
+        out = av_frame_clone(first);
+
+        if (!out)
+            return AVERROR(ENOMEM);
+
+        // output first frame
+        out->pts = (AV_NOPTS_VALUE != first->pts ) ? first->pts * 2 : 
AV_NOPTS_VALUE;
+        out->interlaced_frame = 1;
+        out->pts = av_rescale_q(out->pts, 
reinterlace->preout_time_base, outlink->time_base);
+        ret = ff_filter_frame(outlink, out);
+
+        if (ret < 0)
+            return ret;
+
+        // output the second frame interlaced with first frame
+        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+
+        if (!out)
+            return AVERROR(ENOMEM);
+
+        av_frame_copy_props(out, second);
+        out->interlaced_frame = 1;
+        out->top_field_first = !out->top_field_first;
+        out->pts = first->pts + second->pts;
+        out->pts = ( first->pts == AV_NOPTS_VALUE || second->pts == 
AV_NOPTS_VALUE) ? AV_NOPTS_VALUE : out->pts;
+
+        copy_all_planes(ctx, reinterlace, desc, out, first, second);
+
+        out->pts = av_rescale_q(out->pts, 
reinterlace->preout_time_base, outlink->time_base);
+        ret = ff_filter_frame(outlink, out);
+        break;
+
+    default:
+        av_assert0(0);
+    }
+
+
+
+    return ret;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    ReInterlaceContext *reinterlace = ctx->priv;
+    int i;
+
+    for (i = 0; i < 4; i++)
+        if (reinterlace->black_vec[i])
+            av_free(reinterlace->black_vec[i]);
+
+    av_free(reinterlace->thread_data);
+
+}
+
+static const AVFilterPad reinterlace_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad reinterlace_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_out_props,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_reinterlace = {
+    .name          = "reinterlace",
+    .description   = NULL_IF_CONFIG_SMALL("Various interlace frame 
manipulations"),
+    .priv_size     = sizeof(ReInterlaceContext),
+    .init          = init,
+    .uninit        = uninit,
+    .query_formats = query_formats,
+    .inputs        = reinterlace_inputs,
+    .outputs       = reinterlace_outputs,
+    .priv_class    = &reinterlace_class,
+    .flags         = AVFILTER_FLAG_SLICE_THREADS | 
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
+};
\ No newline at end of file
diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile
index 4d4c5e5..f8b9256 100644
--- a/libavfilter/x86/Makefile
+++ b/libavfilter/x86/Makefile
@@ -16,6 +16,7 @@  OBJS-$(CONFIG_NOISE_FILTER)                  += 
x86/vf_noise.o
  OBJS-$(CONFIG_PP7_FILTER)                    += x86/vf_pp7_init.o
  OBJS-$(CONFIG_PSNR_FILTER)                   += x86/vf_psnr_init.o
  OBJS-$(CONFIG_PULLUP_FILTER)                 += x86/vf_pullup_init.o
+OBJS-$(CONFIG_REINTERLACE_FILTER)            += x86/vf_reinterlace_init.o
  OBJS-$(CONFIG_REMOVEGRAIN_FILTER)            += x86/vf_removegrain_init.o
  OBJS-$(CONFIG_SHOWCQT_FILTER)                += x86/avf_showcqt_init.o
  OBJS-$(CONFIG_SPP_FILTER)                    += x86/vf_spp.o
diff --git a/libavfilter/x86/vf_reinterlace_init.c 
b/libavfilter/x86/vf_reinterlace_init.c
new file mode 100644
index 0000000..5abbf1f
--- /dev/null
+++ b/libavfilter/x86/vf_reinterlace_init.c
@@ -0,0 +1,101 @@ 
+/*
+ * Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/internal.h"
+#include "libavutil/mem.h"
+#include "libavutil/x86/asm.h"
+#include "libavutil/x86/cpu.h"
+
+#include "libavfilter/reinterlace.h"
+
+#if CONFIG_GPL
+
+void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp, ptrdiff_t mref,
+                          ptrdiff_t pref, int clip_max);
+void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp, ptrdiff_t mref,
+                          ptrdiff_t pref, int clip_max);
+void ff_lowpass_line_avx2 (uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp, ptrdiff_t mref,
+                          ptrdiff_t pref, int clip_max);
+
+void ff_lowpass_line_16_sse2(uint8_t *dstp, ptrdiff_t linesize,
+                             const uint8_t *srcp, ptrdiff_t mref,
+                             ptrdiff_t pref, int clip_max);
+void ff_lowpass_line_16_avx (uint8_t *dstp, ptrdiff_t linesize,
+                             const uint8_t *srcp, ptrdiff_t mref,
+                             ptrdiff_t pref, int clip_max);
+void ff_lowpass_line_16_avx2 (uint8_t *dstp, ptrdiff_t linesize,
+                             const uint8_t *srcp, ptrdiff_t mref,
+                             ptrdiff_t pref, int clip_max);
+
+void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize,
+                                  const uint8_t *srcp, ptrdiff_t mref,
+                                  ptrdiff_t pref, int clip_max);
+
+void ff_lowpass_line_complex_12_sse2(uint8_t *dstp, ptrdiff_t linesize,
+                                     const uint8_t *srcp, ptrdiff_t mref,
+                                     ptrdiff_t pref, int clip_max);
+
+av_cold void ff_reinterlace_init_x86(ReInterlaceContext *reinterlace)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (reinterlace->bit_depth > 8) {
+        if (EXTERNAL_SSE2(cpu_flags)) {
+            if (!(reinterlace->flags & FLAG_CVLPF))
+                reinterlace->lowpass_line = ff_lowpass_line_16_sse2;
+            else
+                reinterlace->lowpass_line = 
ff_lowpass_line_complex_12_sse2;
+        }
+        if (EXTERNAL_AVX(cpu_flags))
+            if (!(reinterlace->flags & FLAG_CVLPF))
+                reinterlace->lowpass_line = ff_lowpass_line_16_avx;
+        if (EXTERNAL_AVX2_FAST(cpu_flags)) {
+            if (!(reinterlace->flags & FLAG_CVLPF)) {
+                reinterlace->lowpass_line = ff_lowpass_line_16_avx2;
+            }
+        }
+    } else {
+        if (EXTERNAL_SSE2(cpu_flags)) {
+            if (!(reinterlace->flags & FLAG_CVLPF))
+                reinterlace->lowpass_line = ff_lowpass_line_sse2;
+            else
+                reinterlace->lowpass_line = ff_lowpass_line_complex_sse2;
+        }
+        if (EXTERNAL_AVX(cpu_flags))
+            if (!(reinterlace->flags & FLAG_CVLPF))
+                reinterlace->lowpass_line = ff_lowpass_line_avx;
+        if (EXTERNAL_AVX2_FAST(cpu_flags)) {
+            if (!(reinterlace->flags & FLAG_CVLPF)) {
+                reinterlace->lowpass_line = ff_lowpass_line_avx2;
+            }
+        }
+    }
+}
+
+#elif
+
+av_cold void ff_reinterlace_init_x86(ReInterlaceContext *s) {}
+