1 /*
2  * This file is part of MPlayer.
3  *
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.
8  *
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.
13  *
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.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <inttypes.h>
23 
24 #include "config.h"
25 #include "mp_msg.h"
26 
27 #include "mp_image.h"
28 #include "img_format.h"
29 #include "vf.h"
30 
31 struct vf_priv_s {
32   float sense; // first parameter
33   float level; // second parameter
34   unsigned int imgfmt;
35   int diff;
36   uint32_t max;
37 //  int dfr;
38 //  int rdfr;
39   int was_dint;
40   mp_image_t *pmpi; // previous mpi
41 };
42 
43 #define MAXROWSIZE 1200
44 
config(struct vf_instance * vf,int width,int height,int d_width,int d_height,unsigned int flags,unsigned int outfmt)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)
48 {
49     int rowsize;
50 
51     vf->priv->pmpi = vf_get_image (vf->next, outfmt, MP_IMGTYPE_TEMP,
52                                    0, width, height);
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)
57     {
58       mp_msg (MSGT_VFILTER, MSGL_WARN, "Drop-interlaced filter doesn't support this outfmt :(\n");
59       return 0;
60     }
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;
68     else
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)
73       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);
80 }
81 
put_image(struct vf_instance * vf,mp_image_t * mpi,double pts,double endpts)82 static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
83 {
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;
91     int i, j;
92     register int n1, n2;
93     unsigned char *cur0, *prv0;
94     register unsigned char *cur, *prv;
95 
96     if (rowsize > MAXROWSIZE) rowsize = MAXROWSIZE;
97     // check if nothing to do
98     if (mpi->imgfmt == vf->priv->imgfmt)
99     {
100       cur0 = mpi->planes[0] + mpi->stride[0];
101       prv0 = mpi->planes[0];
102       for (j = 1; j < mpi->height && nok <= max; j++)
103       {
104         cur = cur0;
105         prv = prv0;
106         // analyse row (row0)
107         if (mpi->flags & MP_IMGFLAG_PLANAR) // planar YUV - check luminance
108           for (i = 0; i < rowsize; i++)
109           {
110             if (cur[0] - prv[0] > diff)
111               row0[i] = 1;
112             else if (cur[0] - prv[0] < -diff)
113               row0[i] = -1;
114             else
115               row0[i] = 0;
116             cur++;
117             prv++;
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)) &&
121                 (++nok) > max)
122               break;
123           }
124         else if (mpi->bpp < 24) // RGB/BGR 16 - check all colors
125           for (i = 0; i < rowsize; i++)
126           {
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)
132               row0[i] = 1;
133             else if ((n1&0x1f) - (n2&0x1f) < -diff ||
134                      ((n1>>5)&0x3f) - ((n2>>5)&0x3f) < -diff ||
135                      ((n1>>11)&0x1f) - ((n2>>11)&0x1f) < -diff)
136               row0[i] = -1;
137             else
138               row0[i] = 0;
139             cur += 2;
140             prv += 2;
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)) &&
144                 (++nok) > max)
145               break;
146           }
147         else // RGB/BGR 24/32
148           for (i = 0; i < rowsize; i++)
149           {
150             if (cur[0] - prv[0] > diff ||
151                 cur[1] - prv[1] > diff ||
152                 cur[2] - prv[2] > diff)
153               row0[i] = 1;
154             else if (prv[0] - cur[0] > diff ||
155                      prv[1] - cur[1] > diff ||
156                      prv[2] - cur[2] > diff)
157               row0[i] = -1;
158             else
159               row0[i] = 0;
160             cur += mpi->bpp/8;
161             prv += mpi->bpp/8;
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)) &&
165                 (++nok) > max)
166               break;
167           }
168         cur0 += mpi->stride[0];
169         prv0 += mpi->stride[0];
170         // rotate rows
171         cur = row2;
172         row2 = row1;
173         row1 = row0;
174         row0 = cur;
175       }
176     }
177     // check if number of interlaced is above of max
178     if (nok > max)
179     {
180 //    vf->priv->dfr++;
181       if (vf->priv->was_dint < 1) // can skip at most one frame!
182       {
183         vf->priv->was_dint++;
184 //      vf->priv->rdfr++;
185 //      mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
186         return 0;
187       }
188     }
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, endpts);
192 }
193 
vf_open(vf_instance_t * vf,char * args)194 static int vf_open(vf_instance_t *vf, char *args){
195     vf->config = config;
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;
202     if (args)
203       sscanf (args, "%f:%f", &vf->priv->sense, &vf->priv->level);
204     return 1;
205 }
206 
207 const vf_info_t vf_info_dint = {
208     "drop interlaced frames",
209     "dint",
210     "A.G.",
211     "",
212     vf_open,
213     NULL
214 };
215