vf_mp: remove boxblur wrapper
[ffmpeg.git] / libavfilter / libmpcodecs / vf_kerndeint.c
1 /*
2  * Original AVISynth Filter Copyright (C) 2003 Donald A. Graft
3  *  Adapted to MPlayer by Tobias Diedrich
4  *
5  * This file is part of MPlayer.
6  *
7  * MPlayer is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * MPlayer is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <inttypes.h>
26 #include <math.h>
27
28 #include "mp_msg.h"
29 #include "img_format.h"
30 #include "mp_image.h"
31 #include "vf.h"
32 #include "libvo/fastmemcpy.h"
33
34 //===========================================================================//
35
36 struct vf_priv_s {
37     int    frame;
38     int    map;
39     int    order;
40     int    thresh;
41     int    sharp;
42     int    twoway;
43     int    do_deinterlace;
44 };
45
46
47 /***************************************************************************/
48
49
50 static int config(struct vf_instance *vf,
51     int width, int height, int d_width, int d_height,
52     unsigned int flags, unsigned int outfmt){
53
54     return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
55 }
56
57
58 static void uninit(struct vf_instance *vf)
59 {
60     free(vf->priv);
61 }
62
63 static inline int IsRGB(mp_image_t *mpi)
64 {
65     return mpi->imgfmt == IMGFMT_RGB;
66 }
67
68 static inline int IsYUY2(mp_image_t *mpi)
69 {
70     return mpi->imgfmt == IMGFMT_YUY2;
71 }
72
73 #define PLANAR_Y 0
74 #define PLANAR_U 1
75 #define PLANAR_V 2
76
77 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
78     int cw= mpi->w >> mpi->chroma_x_shift;
79     int ch= mpi->h >> mpi->chroma_y_shift;
80     int W = mpi->w, H = mpi->h;
81     const unsigned char *prvp, *prvpp, *prvpn, *prvpnn, *prvppp, *prvp4p, *prvp4n;
82     const unsigned char *srcp_saved;
83     const unsigned char *srcp, *srcpp, *srcpn, *srcpnn, *srcppp, *srcp3p, *srcp3n, *srcp4p, *srcp4n;
84     unsigned char *dstp, *dstp_saved;
85     int src_pitch;
86     int psrc_pitch;
87     int dst_pitch;
88     int x, y, z;
89     int n = vf->priv->frame++;
90     int val, hi, lo, w, h;
91     double valf;
92     int plane;
93     int threshold = vf->priv->thresh;
94     int order = vf->priv->order;
95     int map = vf->priv->map;
96     int sharp = vf->priv->sharp;
97     int twoway = vf->priv->twoway;
98     mp_image_t *dmpi, *pmpi;
99
100     if(!vf->priv->do_deinterlace)
101         return vf_next_put_image(vf, mpi, pts);
102
103     dmpi=vf_get_image(vf->next,mpi->imgfmt,
104         MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE,
105         mpi->w,mpi->h);
106     pmpi=vf_get_image(vf->next,mpi->imgfmt,
107         MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
108         mpi->w,mpi->h);
109     if(!dmpi) return 0;
110
111     for (z=0; z<mpi->num_planes; z++) {
112         if (z == 0) plane = PLANAR_Y;
113         else if (z == 1) plane = PLANAR_U;
114         else plane = PLANAR_V;
115
116         h = plane == PLANAR_Y ? H : ch;
117         w = plane == PLANAR_Y ? W : cw;
118
119         srcp = srcp_saved = mpi->planes[z];
120         src_pitch = mpi->stride[z];
121         psrc_pitch = pmpi->stride[z];
122         dstp = dstp_saved = dmpi->planes[z];
123         dst_pitch = dmpi->stride[z];
124         srcp = srcp_saved + (1-order) * src_pitch;
125         dstp = dstp_saved + (1-order) * dst_pitch;
126
127         for (y=0; y<h; y+=2) {
128             fast_memcpy(dstp, srcp, w);
129             srcp += 2*src_pitch;
130             dstp += 2*dst_pitch;
131         }
132
133         // Copy through the lines that will be missed below.
134         fast_memcpy(dstp_saved + order*dst_pitch, srcp_saved + (1-order)*src_pitch, w);
135         fast_memcpy(dstp_saved + (2+order)*dst_pitch, srcp_saved + (3-order)*src_pitch, w);
136         fast_memcpy(dstp_saved + (h-2+order)*dst_pitch, srcp_saved + (h-1-order)*src_pitch, w);
137         fast_memcpy(dstp_saved + (h-4+order)*dst_pitch, srcp_saved + (h-3-order)*src_pitch, w);
138         /* For the other field choose adaptively between using the previous field
139            or the interpolant from the current field. */
140
141         prvp = pmpi->planes[z] + 5*psrc_pitch - (1-order)*psrc_pitch;
142         prvpp = prvp - psrc_pitch;
143         prvppp = prvp - 2*psrc_pitch;
144         prvp4p = prvp - 4*psrc_pitch;
145         prvpn = prvp + psrc_pitch;
146         prvpnn = prvp + 2*psrc_pitch;
147         prvp4n = prvp + 4*psrc_pitch;
148         srcp = srcp_saved + 5*src_pitch - (1-order)*src_pitch;
149         srcpp = srcp - src_pitch;
150         srcppp = srcp - 2*src_pitch;
151         srcp3p = srcp - 3*src_pitch;
152         srcp4p = srcp - 4*src_pitch;
153         srcpn = srcp + src_pitch;
154         srcpnn = srcp + 2*src_pitch;
155         srcp3n = srcp + 3*src_pitch;
156         srcp4n = srcp + 4*src_pitch;
157         dstp =  dstp_saved  + 5*dst_pitch - (1-order)*dst_pitch;
158         for (y = 5 - (1-order); y <= h - 5 - (1-order); y+=2)
159         {
160             for (x = 0; x < w; x++)
161             {
162                 if ((threshold == 0) || (n == 0) ||
163                     (abs((int)prvp[x] - (int)srcp[x]) > threshold) ||
164                     (abs((int)prvpp[x] - (int)srcpp[x]) > threshold) ||
165                     (abs((int)prvpn[x] - (int)srcpn[x]) > threshold))
166                 {
167                     if (map == 1)
168                     {
169                         int g = x & ~3;
170                         if (IsRGB(mpi) == 1)
171                         {
172                             dstp[g++] = 255;
173                             dstp[g++] = 255;
174                             dstp[g++] = 255;
175                             dstp[g] = 255;
176                             x = g;
177                         }
178                         else if (IsYUY2(mpi) == 1)
179                         {
180                             dstp[g++] = 235;
181                             dstp[g++] = 128;
182                             dstp[g++] = 235;
183                             dstp[g] = 128;
184                             x = g;
185                         }
186                         else
187                         {
188                             if (plane == PLANAR_Y) dstp[x] = 235;
189                             else dstp[x] = 128;
190                         }
191                     }
192                     else
193                     {
194                         if (IsRGB(mpi))
195                         {
196                             hi = 255;
197                             lo = 0;
198                         }
199                         else if (IsYUY2(mpi))
200                         {
201                             hi = (x & 1) ? 240 : 235;
202                             lo = 16;
203                         }
204                         else
205                         {
206                             hi = (plane == PLANAR_Y) ? 235 : 240;
207                             lo = 16;
208                         }
209
210                         if (sharp == 1)
211                         {
212                             if (twoway == 1)
213                                 valf = + 0.526*((int)srcpp[x] + (int)srcpn[x])
214                                    + 0.170*((int)srcp[x] + (int)prvp[x])
215                                    - 0.116*((int)srcppp[x] + (int)srcpnn[x] + (int)prvppp[x] + (int)prvpnn[x])
216                                    - 0.026*((int)srcp3p[x] + (int)srcp3n[x])
217                                    + 0.031*((int)srcp4p[x] + (int)srcp4n[x] + (int)prvp4p[x] + (int)prvp4n[x]);
218                             else
219                                 valf = + 0.526*((int)srcpp[x] + (int)srcpn[x])
220                                    + 0.170*((int)prvp[x])
221                                    - 0.116*((int)prvppp[x] + (int)prvpnn[x])
222                                    - 0.026*((int)srcp3p[x] + (int)srcp3n[x])
223                                    + 0.031*((int)prvp4p[x] + (int)prvp4p[x]);
224                             if (valf > hi) valf = hi;
225                             else if (valf < lo) valf = lo;
226                             dstp[x] = (int) valf;
227                         }
228                         else
229                         {
230                             if (twoway == 1)
231                                 val = (8*((int)srcpp[x] + (int)srcpn[x]) + 2*((int)srcp[x] + (int)prvp[x]) -
232                                     (int)(srcppp[x]) - (int)(srcpnn[x]) -
233                                     (int)(prvppp[x]) - (int)(prvpnn[x])) >> 4;
234                             else
235                                 val = (8*((int)srcpp[x] + (int)srcpn[x]) + 2*((int)prvp[x]) -
236                                     (int)(prvppp[x]) - (int)(prvpnn[x])) >> 4;
237                             if (val > hi) val = hi;
238                             else if (val < lo) val = lo;
239                             dstp[x] = (int) val;
240                         }
241                     }
242                 }
243                 else
244                 {
245                     dstp[x] = srcp[x];
246                 }
247             }
248             prvp  += 2*psrc_pitch;
249             prvpp  += 2*psrc_pitch;
250             prvppp  += 2*psrc_pitch;
251             prvpn  += 2*psrc_pitch;
252             prvpnn  += 2*psrc_pitch;
253             prvp4p  += 2*psrc_pitch;
254             prvp4n  += 2*psrc_pitch;
255             srcp  += 2*src_pitch;
256             srcpp += 2*src_pitch;
257             srcppp += 2*src_pitch;
258             srcp3p += 2*src_pitch;
259             srcp4p += 2*src_pitch;
260             srcpn += 2*src_pitch;
261             srcpnn += 2*src_pitch;
262             srcp3n += 2*src_pitch;
263             srcp4n += 2*src_pitch;
264             dstp  += 2*dst_pitch;
265         }
266
267         srcp = mpi->planes[z];
268         dstp = pmpi->planes[z];
269         for (y=0; y<h; y++) {
270             fast_memcpy(dstp, srcp, w);
271             srcp += src_pitch;
272             dstp += psrc_pitch;
273         }
274     }
275
276     return vf_next_put_image(vf,dmpi, pts);
277 }
278
279 //===========================================================================//
280
281 static int query_format(struct vf_instance *vf, unsigned int fmt){
282         switch(fmt)
283     {
284     case IMGFMT_YV12:
285     case IMGFMT_RGB:
286     case IMGFMT_YUY2:
287         return vf_next_query_format(vf, fmt);
288     }
289     return 0;
290 }
291
292 static int control(struct vf_instance *vf, int request, void* data){
293     switch (request)
294     {
295     case VFCTRL_GET_DEINTERLACE:
296         *(int*)data = vf->priv->do_deinterlace;
297         return CONTROL_OK;
298     case VFCTRL_SET_DEINTERLACE:
299         vf->priv->do_deinterlace = *(int*)data;
300         return CONTROL_OK;
301     }
302     return vf_next_control (vf, request, data);
303 }
304
305 static int vf_open(vf_instance_t *vf, char *args){
306
307     vf->control=control;
308     vf->config=config;
309     vf->put_image=put_image;
310         vf->query_format=query_format;
311         vf->uninit=uninit;
312     vf->priv=malloc(sizeof(struct vf_priv_s));
313         memset(vf->priv, 0, sizeof(struct vf_priv_s));
314
315     vf->priv->frame = 0;
316
317     vf->priv->map = 0;
318     vf->priv->order = 0;
319     vf->priv->thresh = 10;
320     vf->priv->sharp = 0;
321     vf->priv->twoway = 0;
322     vf->priv->do_deinterlace=1;
323
324         if (args)
325         {
326             sscanf(args, "%d:%d:%d:%d:%d",
327         &vf->priv->thresh, &vf->priv->map,
328         &vf->priv->order, &vf->priv->sharp,
329         &vf->priv->twoway);
330         }
331     if (vf->priv->order > 1) vf->priv->order = 1;
332
333     return 1;
334 }
335
336 const vf_info_t vf_info_kerndeint = {
337     "Kernel Deinterlacer",
338     "kerndeint",
339     "Donald Graft",
340     "",
341     vf_open,
342     NULL
343 };
344
345 //===========================================================================//