FFmpeg
vf_kerndeint.c
Go to the documentation of this file.
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;
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 ff_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 ff_vf_next_put_image(vf, mpi, pts);
102 
103  dmpi=ff_vf_get_image(vf->next,mpi->imgfmt,
105  mpi->w,mpi->h);
106  pmpi=ff_vf_get_image(vf->next,mpi->imgfmt,
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 ff_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 ff_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  {
296  *(int*)data = vf->priv->do_deinterlace;
297  return CONTROL_OK;
299  vf->priv->do_deinterlace = *(int*)data;
300  return CONTROL_OK;
301  }
302  return ff_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;
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 
337  "Kernel Deinterlacer",
338  "kerndeint",
339  "Donald Graft",
340  "",
341  vf_open,
342  NULL
343 };
344 
345 //===========================================================================//