Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_phase.c @ e4852fb3

History | View | Annotate | Download (8.78 KB)

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 <limits.h>
23

    
24
#include "config.h"
25
#include "mp_msg.h"
26

    
27
#include "img_format.h"
28
#include "mp_image.h"
29
#include "vf.h"
30

    
31
#include "libvo/fastmemcpy.h"
32

    
33
enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST,
34
            TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE,
35
            ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE };
36

    
37
#define fixed_mode(p) ((p)<=BOTTOM_FIRST)
38

    
39
struct vf_priv_s
40
   {
41
   enum mode mode;
42
   int verbose;
43
   unsigned char *buf[3];
44
   };
45

    
46
/*
47
 * Copy fields from either current or buffered previous frame to the
48
 * output and store the current frame unmodified to the buffer.
49
 */
50

    
51
static void do_plane(unsigned char *to, unsigned char *from,
52
                     int w, int h, int ts, int fs,
53
                     unsigned char **bufp, enum mode mode)
54
   {
55
   unsigned char *buf, *end;
56
   int top;
57

    
58
   if(!*bufp)
59
      {
60
      mode=PROGRESSIVE;
61
      if(!(*bufp=malloc(h*w))) return;
62
      }
63

    
64
   for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
65
      {
66
      fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
67
      fast_memcpy(buf, from, w);
68
      }
69
   }
70

    
71
/*
72
 * This macro interpolates the value of both fields at a point halfway
73
 * between lines and takes the squared difference. In field resolution
74
 * the point is a quarter pixel below a line in one field and a quarter
75
 * pixel above a line in other.
76
 *
77
 * (the result is actually multiplied by 25)
78
 */
79

    
80
#define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t)
81

    
82
/*
83
 * Find which field combination has the smallest average squared difference
84
 * between the fields.
85
 */
86

    
87
static enum mode analyze_plane(unsigned char *old, unsigned char *new,
88
                               int w, int h, int os, int ns, enum mode mode,
89
                               int verbose, int fields)
90
   {
91
   double bdiff, pdiff, tdiff, scale;
92
   int bdif, tdif, pdif;
93
   int top, t;
94
   unsigned char *end, *rend;
95

    
96
   if(mode==AUTO)
97
      mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
98
         TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE;
99
   else if(mode==AUTO_ANALYZE)
100
      mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
101
         TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE;
102

    
103
   if(fixed_mode(mode))
104
      bdiff=pdiff=tdiff=65536.0;
105
   else
106
      {
107
      bdiff=pdiff=tdiff=0.0;
108

    
109
      for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
110
          new<end; new+=ns-w, old+=os-w, top^=1)
111
         {
112
         pdif=tdif=bdif=0;
113

    
114
         switch(mode)
115
            {
116
            case TOP_FIRST_ANALYZE:
117
               if(top)
118
                  for(rend=new+w; new<rend; new++, old++)
119
                     pdif+=diff(new, ns, new, ns),
120
                     tdif+=diff(new, ns, old, os);
121
               else
122
                  for(rend=new+w; new<rend; new++, old++)
123
                     pdif+=diff(new, ns, new, ns),
124
                     tdif+=diff(old, os, new, ns);
125
               break;
126

    
127
            case BOTTOM_FIRST_ANALYZE:
128
               if(top)
129
                  for(rend=new+w; new<rend; new++, old++)
130
                     pdif+=diff(new, ns, new, ns),
131
                     bdif+=diff(old, os, new, ns);
132
               else
133
                  for(rend=new+w; new<rend; new++, old++)
134
                     pdif+=diff(new, ns, new, ns),
135
                     bdif+=diff(new, ns, old, os);
136
               break;
137

    
138
            case ANALYZE:
139
               if(top)
140
                  for(rend=new+w; new<rend; new++, old++)
141
                     tdif+=diff(new, ns, old, os),
142
                     bdif+=diff(old, os, new, ns);
143
               else
144
                  for(rend=new+w; new<rend; new++, old++)
145
                     bdif+=diff(new, ns, old, os),
146
                     tdif+=diff(old, os, new, ns);
147
               break;
148

    
149
            default: /* FULL_ANALYZE */
150
               if(top)
151
                  for(rend=new+w; new<rend; new++, old++)
152
                     pdif+=diff(new, ns, new, ns),
153
                     tdif+=diff(new, ns, old, os),
154
                     bdif+=diff(old, os, new, ns);
155
               else
156
                  for(rend=new+w; new<rend; new++, old++)
157
                     pdif+=diff(new, ns, new, ns),
158
                     bdif+=diff(new, ns, old, os),
159
                     tdif+=diff(old, os, new, ns);
160
            }
161

    
162
         pdiff+=(double)pdif;
163
         tdiff+=(double)tdif;
164
         bdiff+=(double)bdif;
165
         }
166

    
167
      scale=1.0/(w*(h-3))/25.0;
168
      pdiff*=scale;
169
      tdiff*=scale;
170
      bdiff*=scale;
171

    
172
      if(mode==TOP_FIRST_ANALYZE)
173
         bdiff=65536.0;
174
      else if(mode==BOTTOM_FIRST_ANALYZE)
175
         tdiff=65536.0;
176
      else if(mode==ANALYZE)
177
         pdiff=65536.0;
178

    
179
      if(bdiff<pdiff && bdiff<tdiff)
180
         mode=BOTTOM_FIRST;
181
      else if(tdiff<pdiff && tdiff<bdiff)
182
         mode=TOP_FIRST;
183
      else
184
         mode=PROGRESSIVE;
185
      }
186

    
187
   if( mp_msg_test(MSGT_VFILTER,MSGL_V) )
188
      {
189
      mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
190
      if(tdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO,"     N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff);
191
      if(bdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO,"     N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff);
192
      if(pdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO,"     N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff);
193
      mp_msg(MSGT_VFILTER, MSGL_INFO,"        \n");
194
      }
195

    
196
   return mode;
197
   }
198

    
199
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
200
   {
201
   mp_image_t *dmpi;
202
   int w;
203
   enum mode mode;
204

    
205
   if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt,
206
                          MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
207
                          mpi->w, mpi->h)))
208
      return 0;
209

    
210
   w=dmpi->w;
211
   if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
212
      w*=dmpi->bpp/8;
213

    
214
   mode=vf->priv->mode;
215

    
216
   if(!vf->priv->buf[0])
217
      mode=PROGRESSIVE;
218
   else
219
      mode=analyze_plane(vf->priv->buf[0], mpi->planes[0],
220
                         w, dmpi->h, w, mpi->stride[0], mode,
221
                         vf->priv->verbose, mpi->fields);
222

    
223
   do_plane(dmpi->planes[0], mpi->planes[0],
224
            w, dmpi->h,
225
            dmpi->stride[0], mpi->stride[0],
226
            &vf->priv->buf[0], mode);
227

    
228
   if(dmpi->flags&MP_IMGFLAG_PLANAR)
229
      {
230
      do_plane(dmpi->planes[1], mpi->planes[1],
231
               dmpi->chroma_width, dmpi->chroma_height,
232
               dmpi->stride[1], mpi->stride[1],
233
               &vf->priv->buf[1], mode);
234
      do_plane(dmpi->planes[2], mpi->planes[2],
235
               dmpi->chroma_width, dmpi->chroma_height,
236
               dmpi->stride[2], mpi->stride[2],
237
               &vf->priv->buf[2], mode);
238
      }
239

    
240
   return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
241
   }
242

    
243
static void uninit(struct vf_instance *vf)
244
   {
245
   free(vf->priv->buf[0]);
246
   free(vf->priv->buf[1]);
247
   free(vf->priv->buf[2]);
248
   free(vf->priv);
249
   }
250

    
251
static int vf_open(vf_instance_t *vf, char *args)
252
   {
253
   vf->put_image = put_image;
254
   vf->uninit = uninit;
255
   vf->default_reqs = VFCAP_ACCEPT_STRIDE;
256

    
257
   if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
258
      {
259
      uninit(vf);
260
      return 0;
261
      }
262

    
263
   vf->priv->mode=AUTO_ANALYZE;
264
   vf->priv->verbose=0;
265

    
266
   while(args && *args)
267
      {
268
      switch(*args)
269
         {
270
         case 't': vf->priv->mode=TOP_FIRST;            break;
271
         case 'a': vf->priv->mode=AUTO;                 break;
272
         case 'b': vf->priv->mode=BOTTOM_FIRST;         break;
273
         case 'u': vf->priv->mode=ANALYZE;              break;
274
         case 'T': vf->priv->mode=TOP_FIRST_ANALYZE;    break;
275
         case 'A': vf->priv->mode=AUTO_ANALYZE;         break;
276
         case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
277
         case 'U': vf->priv->mode=FULL_ANALYZE;         break;
278
         case 'p': vf->priv->mode=PROGRESSIVE;          break;
279
         case 'v': vf->priv->verbose=1;                 break;
280
         case ':': break;
281

    
282
         default:
283
            uninit(vf);
284
            return 0; /* bad args */
285
         }
286

    
287
      if( (args=strchr(args, ':')) ) args++;
288
      }
289

    
290
   return 1;
291
   }
292

    
293
const vf_info_t vf_info_phase =
294
   {
295
   "phase shift fields",
296
   "phase",
297
   "Ville Saari",
298
   "",
299
   vf_open,
300
   NULL
301
   };