• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavfilter/libmpcodecs/vf_phase.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of MPlayer.
00003  *
00004  * MPlayer is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * MPlayer is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License along
00015  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <limits.h>
00023 
00024 #include "config.h"
00025 #include "mp_msg.h"
00026 
00027 #include "img_format.h"
00028 #include "mp_image.h"
00029 #include "vf.h"
00030 
00031 #include "libvo/fastmemcpy.h"
00032 
00033 enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST,
00034             TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE,
00035             ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE };
00036 
00037 #define fixed_mode(p) ((p)<=BOTTOM_FIRST)
00038 
00039 struct vf_priv_s
00040    {
00041    enum mode mode;
00042    int verbose;
00043    unsigned char *buf[3];
00044    };
00045 
00046 /*
00047  * Copy fields from either current or buffered previous frame to the
00048  * output and store the current frame unmodified to the buffer.
00049  */
00050 
00051 static void do_plane(unsigned char *to, unsigned char *from,
00052                      int w, int h, int ts, int fs,
00053                      unsigned char **bufp, enum mode mode)
00054    {
00055    unsigned char *buf, *end;
00056    int top;
00057 
00058    if(!*bufp)
00059       {
00060       mode=PROGRESSIVE;
00061       if(!(*bufp=malloc(h*w))) return;
00062       }
00063 
00064    for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1)
00065       {
00066       fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
00067       fast_memcpy(buf, from, w);
00068       }
00069    }
00070 
00071 /*
00072  * This macro interpolates the value of both fields at a point halfway
00073  * between lines and takes the squared difference. In field resolution
00074  * the point is a quarter pixel below a line in one field and a quarter
00075  * pixel above a line in other.
00076  *
00077  * (the result is actually multiplied by 25)
00078  */
00079 
00080 #define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t)
00081 
00082 /*
00083  * Find which field combination has the smallest average squared difference
00084  * between the fields.
00085  */
00086 
00087 static enum mode analyze_plane(unsigned char *old, unsigned char *new,
00088                                int w, int h, int os, int ns, enum mode mode,
00089                                int verbose, int fields)
00090    {
00091    double bdiff, pdiff, tdiff, scale;
00092    int bdif, tdif, pdif;
00093    int top, t;
00094    unsigned char *end, *rend;
00095 
00096    if(mode==AUTO)
00097       mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
00098          TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE;
00099    else if(mode==AUTO_ANALYZE)
00100       mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST?
00101          TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE;
00102 
00103    if(fixed_mode(mode))
00104       bdiff=pdiff=tdiff=65536.0;
00105    else
00106       {
00107       bdiff=pdiff=tdiff=0.0;
00108 
00109       for(end=new+(h-2)*ns, new+=ns, old+=os, top=0;
00110           new<end; new+=ns-w, old+=os-w, top^=1)
00111          {
00112          pdif=tdif=bdif=0;
00113 
00114          switch(mode)
00115             {
00116             case TOP_FIRST_ANALYZE:
00117                if(top)
00118                   for(rend=new+w; new<rend; new++, old++)
00119                      pdif+=diff(new, ns, new, ns),
00120                      tdif+=diff(new, ns, old, os);
00121                else
00122                   for(rend=new+w; new<rend; new++, old++)
00123                      pdif+=diff(new, ns, new, ns),
00124                      tdif+=diff(old, os, new, ns);
00125                break;
00126 
00127             case BOTTOM_FIRST_ANALYZE:
00128                if(top)
00129                   for(rend=new+w; new<rend; new++, old++)
00130                      pdif+=diff(new, ns, new, ns),
00131                      bdif+=diff(old, os, new, ns);
00132                else
00133                   for(rend=new+w; new<rend; new++, old++)
00134                      pdif+=diff(new, ns, new, ns),
00135                      bdif+=diff(new, ns, old, os);
00136                break;
00137 
00138             case ANALYZE:
00139                if(top)
00140                   for(rend=new+w; new<rend; new++, old++)
00141                      tdif+=diff(new, ns, old, os),
00142                      bdif+=diff(old, os, new, ns);
00143                else
00144                   for(rend=new+w; new<rend; new++, old++)
00145                      bdif+=diff(new, ns, old, os),
00146                      tdif+=diff(old, os, new, ns);
00147                break;
00148 
00149             default: /* FULL_ANALYZE */
00150                if(top)
00151                   for(rend=new+w; new<rend; new++, old++)
00152                      pdif+=diff(new, ns, new, ns),
00153                      tdif+=diff(new, ns, old, os),
00154                      bdif+=diff(old, os, new, ns);
00155                else
00156                   for(rend=new+w; new<rend; new++, old++)
00157                      pdif+=diff(new, ns, new, ns),
00158                      bdif+=diff(new, ns, old, os),
00159                      tdif+=diff(old, os, new, ns);
00160             }
00161 
00162          pdiff+=(double)pdif;
00163          tdiff+=(double)tdif;
00164          bdiff+=(double)bdif;
00165          }
00166 
00167       scale=1.0/(w*(h-3))/25.0;
00168       pdiff*=scale;
00169       tdiff*=scale;
00170       bdiff*=scale;
00171 
00172       if(mode==TOP_FIRST_ANALYZE)
00173          bdiff=65536.0;
00174       else if(mode==BOTTOM_FIRST_ANALYZE)
00175          tdiff=65536.0;
00176       else if(mode==ANALYZE)
00177          pdiff=65536.0;
00178 
00179       if(bdiff<pdiff && bdiff<tdiff)
00180          mode=BOTTOM_FIRST;
00181       else if(tdiff<pdiff && tdiff<bdiff)
00182          mode=TOP_FIRST;
00183       else
00184          mode=PROGRESSIVE;
00185       }
00186 
00187    if( mp_msg_test(MSGT_VFILTER,MSGL_V) )
00188       {
00189       mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
00190       if(tdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO,"     N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff);
00191       if(bdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO,"     N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff);
00192       if(pdiff==65536.0) mp_msg(MSGT_VFILTER, MSGL_INFO,"     N/A "); else mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff);
00193       mp_msg(MSGT_VFILTER, MSGL_INFO,"        \n");
00194       }
00195 
00196    return mode;
00197    }
00198 
00199 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
00200    {
00201    mp_image_t *dmpi;
00202    int w;
00203    enum mode mode;
00204 
00205    if(!(dmpi=vf_get_image(vf->next, mpi->imgfmt,
00206                           MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
00207                           mpi->w, mpi->h)))
00208       return 0;
00209 
00210    w=dmpi->w;
00211    if(!(dmpi->flags&MP_IMGFLAG_PLANAR))
00212       w*=dmpi->bpp/8;
00213 
00214    mode=vf->priv->mode;
00215 
00216    if(!vf->priv->buf[0])
00217       mode=PROGRESSIVE;
00218    else
00219       mode=analyze_plane(vf->priv->buf[0], mpi->planes[0],
00220                          w, dmpi->h, w, mpi->stride[0], mode,
00221                          vf->priv->verbose, mpi->fields);
00222 
00223    do_plane(dmpi->planes[0], mpi->planes[0],
00224             w, dmpi->h,
00225             dmpi->stride[0], mpi->stride[0],
00226             &vf->priv->buf[0], mode);
00227 
00228    if(dmpi->flags&MP_IMGFLAG_PLANAR)
00229       {
00230       do_plane(dmpi->planes[1], mpi->planes[1],
00231                dmpi->chroma_width, dmpi->chroma_height,
00232                dmpi->stride[1], mpi->stride[1],
00233                &vf->priv->buf[1], mode);
00234       do_plane(dmpi->planes[2], mpi->planes[2],
00235                dmpi->chroma_width, dmpi->chroma_height,
00236                dmpi->stride[2], mpi->stride[2],
00237                &vf->priv->buf[2], mode);
00238       }
00239 
00240    return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
00241    }
00242 
00243 static void uninit(struct vf_instance *vf)
00244    {
00245    free(vf->priv->buf[0]);
00246    free(vf->priv->buf[1]);
00247    free(vf->priv->buf[2]);
00248    free(vf->priv);
00249    }
00250 
00251 static int vf_open(vf_instance_t *vf, char *args)
00252    {
00253    vf->put_image = put_image;
00254    vf->uninit = uninit;
00255    vf->default_reqs = VFCAP_ACCEPT_STRIDE;
00256 
00257    if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s))))
00258       {
00259       uninit(vf);
00260       return 0;
00261       }
00262 
00263    vf->priv->mode=AUTO_ANALYZE;
00264    vf->priv->verbose=0;
00265 
00266    while(args && *args)
00267       {
00268       switch(*args)
00269          {
00270          case 't': vf->priv->mode=TOP_FIRST;            break;
00271          case 'a': vf->priv->mode=AUTO;                 break;
00272          case 'b': vf->priv->mode=BOTTOM_FIRST;         break;
00273          case 'u': vf->priv->mode=ANALYZE;              break;
00274          case 'T': vf->priv->mode=TOP_FIRST_ANALYZE;    break;
00275          case 'A': vf->priv->mode=AUTO_ANALYZE;         break;
00276          case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break;
00277          case 'U': vf->priv->mode=FULL_ANALYZE;         break;
00278          case 'p': vf->priv->mode=PROGRESSIVE;          break;
00279          case 'v': vf->priv->verbose=1;                 break;
00280          case ':': break;
00281 
00282          default:
00283             uninit(vf);
00284             return 0; /* bad args */
00285          }
00286 
00287       if( (args=strchr(args, ':')) ) args++;
00288       }
00289 
00290    return 1;
00291    }
00292 
00293 const vf_info_t vf_info_phase =
00294    {
00295    "phase shift fields",
00296    "phase",
00297    "Ville Saari",
00298    "",
00299    vf_open,
00300    NULL
00301    };

Generated on Fri Feb 22 2013 07:24:30 for FFmpeg by  doxygen 1.7.1