2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "img_format.h"
32 float sense; // first parameter
33 float level; // second parameter
40 mp_image_t *pmpi; // previous mpi
43 #define MAXROWSIZE 1200
45 static int config (struct vf_instance *vf,
46 int width, int height, int d_width, int d_height,
47 unsigned int flags, unsigned int outfmt)
51 vf->priv->pmpi = vf_get_image (vf->next, outfmt, MP_IMGTYPE_TEMP,
53 if (!(vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) &&
54 outfmt != IMGFMT_RGB32 && outfmt != IMGFMT_BGR32 &&
55 outfmt != IMGFMT_RGB24 && outfmt != IMGFMT_BGR24 &&
56 outfmt != IMGFMT_RGB16 && outfmt != IMGFMT_BGR16)
58 mp_msg (MSGT_VFILTER, MSGL_WARN, "Drop-interlaced filter doesn't support this outfmt :(\n");
61 vf->priv->imgfmt = outfmt;
62 // recalculate internal values
63 rowsize = vf->priv->pmpi->width;
64 if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
65 vf->priv->max = vf->priv->level * vf->priv->pmpi->height * rowsize / 2;
66 if (vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) // planar YUV
67 vf->priv->diff = vf->priv->sense * 256;
69 vf->priv->diff = vf->priv->sense * (1 << (vf->priv->pmpi->bpp/3));
70 if (vf->priv->diff < 0) vf->priv->diff = 0;
71 if (!(vf->priv->pmpi->flags & MP_IMGFLAG_PLANAR) &&
72 vf->priv->pmpi->bpp < 24 && vf->priv->diff > 31)
74 mp_msg (MSGT_VFILTER, MSGL_INFO, "Drop-interlaced: %dx%d diff %d / level %u\n",
75 vf->priv->pmpi->width, vf->priv->pmpi->height,
76 vf->priv->diff, (unsigned int)vf->priv->max);
77 // vf->priv->rdfr = vf->priv->dfr = 0;
78 vf->priv->was_dint = 0;
79 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
82 static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts)
84 int8_t rrow0[MAXROWSIZE];
85 int8_t rrow1[MAXROWSIZE];
86 int8_t rrow2[MAXROWSIZE];
87 int8_t *row0 = rrow0, *row1 = rrow1, *row2 = rrow2/*, *row3 = rrow3*/;
88 int rowsize = mpi->width;
89 uint32_t nok = 0, max = vf->priv->max;
90 int diff = vf->priv->diff;
93 unsigned char *cur0, *prv0;
94 register unsigned char *cur, *prv;
96 if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
97 // check if nothing to do
98 if (mpi->imgfmt == vf->priv->imgfmt)
100 cur0 = mpi->planes[0] + mpi->stride[0];
101 prv0 = mpi->planes[0];
102 for (j = 1; j < mpi->height && nok <= max; j++)
106 // analyse row (row0)
107 if (mpi->flags & MP_IMGFLAG_PLANAR) // planar YUV - check luminance
108 for (i = 0; i < rowsize; i++)
110 if (cur[0] - prv[0] > diff)
112 else if (cur[0] - prv[0] < -diff)
118 // check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
119 // but row3 is 1 so it's interlaced ptr (nok++)
120 if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
124 else if (mpi->bpp < 24) // RGB/BGR 16 - check all colors
125 for (i = 0; i < rowsize; i++)
127 n1 = cur[0] + (cur[1]<<8);
128 n2 = prv[0] + (prv[1]<<8);
129 if ((n1&0x1f) - (n2&0x1f) > diff ||
130 ((n1>>5)&0x3f) - ((n2>>5)&0x3f) > diff ||
131 ((n1>>11)&0x1f) - ((n2>>11)&0x1f) > diff)
133 else if ((n1&0x1f) - (n2&0x1f) < -diff ||
134 ((n1>>5)&0x3f) - ((n2>>5)&0x3f) < -diff ||
135 ((n1>>11)&0x1f) - ((n2>>11)&0x1f) < -diff)
141 // check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
142 // but row3 is 1 so it's interlaced ptr (nok++)
143 if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
147 else // RGB/BGR 24/32
148 for (i = 0; i < rowsize; i++)
150 if (cur[0] - prv[0] > diff ||
151 cur[1] - prv[1] > diff ||
152 cur[2] - prv[2] > diff)
154 else if (prv[0] - cur[0] > diff ||
155 prv[1] - cur[1] > diff ||
156 prv[2] - cur[2] > diff)
162 // check if row0 is 1 but row1 is 0, and row2 is 1 or row2 is 0
163 // but row3 is 1 so it's interlaced ptr (nok++)
164 if (j > 2 && row0[i] > 0 && (row1[i] < 0 || (!row1[i] && row2[i] < 0)) &&
168 cur0 += mpi->stride[0];
169 prv0 += mpi->stride[0];
177 // check if number of interlaced is above of max
181 if (vf->priv->was_dint < 1) // can skip at most one frame!
183 vf->priv->was_dint++;
185 // mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
189 vf->priv->was_dint = 0;
190 // mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
191 return vf_next_put_image (vf, mpi, pts);
194 static int vf_open(vf_instance_t *vf, char *args){
196 vf->put_image = put_image;
197 // vf->default_reqs=VFCAP_ACCEPT_STRIDE;
198 vf->priv = malloc (sizeof(struct vf_priv_s));
199 vf->priv->sense = 0.1;
200 vf->priv->level = 0.15;
201 vf->priv->pmpi = NULL;
203 sscanf (args, "%f:%f", &vf->priv->sense, &vf->priv->level);
207 const vf_info_t vf_info_dint = {
208 "drop interlaced frames",