~ubuntu-branches/ubuntu/oneiric/mplayer2/oneiric-proposed

« back to all changes in this revision

Viewing changes to mplayer/libmpcodecs/vf_phase.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-03-20 22:48:03 UTC
  • Revision ID: james.westby@ubuntu.com-20110320224803-kc2nlrxz6pcphmf1
Tags: upstream-2.0~rc2
ImportĀ upstreamĀ versionĀ 2.0~rc2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
   };