mirror of https://github.com/FFmpeg/FFmpeg.git
The filter was ported to a native libavfilter filter. Signed-off-by: Paul B Mahol <onemda@gmail.com>pull/35/head
parent
3dd4b6ea41
commit
916549cb1e
5 changed files with 1 additions and 308 deletions
@ -1,303 +0,0 @@ |
||||
/*
|
||||
* This file is part of MPlayer. |
||||
* |
||||
* MPlayer is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* MPlayer is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along |
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc., |
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <limits.h> |
||||
|
||||
#include "config.h" |
||||
#include "mp_msg.h" |
||||
|
||||
#include "img_format.h" |
||||
#include "mp_image.h" |
||||
#include "vf.h" |
||||
|
||||
#include "libvo/fastmemcpy.h" |
||||
|
||||
enum mode { PROGRESSIVE, TOP_FIRST, BOTTOM_FIRST, |
||||
TOP_FIRST_ANALYZE, BOTTOM_FIRST_ANALYZE, |
||||
ANALYZE, FULL_ANALYZE, AUTO, AUTO_ANALYZE }; |
||||
|
||||
#define fixed_mode(p) ((p)<=BOTTOM_FIRST) |
||||
|
||||
struct vf_priv_s |
||||
{ |
||||
enum mode mode; |
||||
int verbose; |
||||
unsigned char *buf[3]; |
||||
}; |
||||
|
||||
/*
|
||||
* Copy fields from either current or buffered previous frame to the |
||||
* output and store the current frame unmodified to the buffer. |
||||
*/ |
||||
|
||||
static void do_plane(unsigned char *to, unsigned char *from, |
||||
int w, int h, int ts, int fs, |
||||
unsigned char **bufp, enum mode mode) |
||||
{ |
||||
unsigned char *buf, *end; |
||||
int top; |
||||
|
||||
if(!*bufp) |
||||
{ |
||||
mode=PROGRESSIVE; |
||||
if(!(*bufp=malloc(h*w))) return; |
||||
} |
||||
|
||||
for(end=to+h*ts, buf=*bufp, top=1; to<end; from+=fs, to+=ts, buf+=w, top^=1) |
||||
{ |
||||
fast_memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w); |
||||
fast_memcpy(buf, from, w); |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* This macro interpolates the value of both fields at a point halfway |
||||
* between lines and takes the squared difference. In field resolution |
||||
* the point is a quarter pixel below a line in one field and a quarter |
||||
* pixel above a line in other. |
||||
* |
||||
* (the result is actually multiplied by 25) |
||||
*/ |
||||
|
||||
#define diff(a, as, b, bs) (t=((*a-b[bs])<<2)+a[as<<1]-b[-bs], t*t) |
||||
|
||||
/*
|
||||
* Find which field combination has the smallest average squared difference |
||||
* between the fields. |
||||
*/ |
||||
|
||||
static enum mode analyze_plane(unsigned char *old, unsigned char *new, |
||||
int w, int h, int os, int ns, enum mode mode, |
||||
int verbose, int fields) |
||||
{ |
||||
double bdiff, pdiff, tdiff, scale; |
||||
int bdif, tdif, pdif; |
||||
int top, t; |
||||
unsigned char *end, *rend; |
||||
|
||||
if(mode==AUTO) |
||||
mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST? |
||||
TOP_FIRST:BOTTOM_FIRST:PROGRESSIVE; |
||||
else if(mode==AUTO_ANALYZE) |
||||
mode=fields&MP_IMGFIELD_ORDERED?fields&MP_IMGFIELD_TOP_FIRST? |
||||
TOP_FIRST_ANALYZE:BOTTOM_FIRST_ANALYZE:FULL_ANALYZE; |
||||
|
||||
if(fixed_mode(mode)) |
||||
bdiff=pdiff=tdiff=65536.0; |
||||
else |
||||
{ |
||||
bdiff=pdiff=tdiff=0.0; |
||||
|
||||
for(end=new+(h-2)*ns, new+=ns, old+=os, top=0; |
||||
new<end; new+=ns-w, old+=os-w, top^=1) |
||||
{ |
||||
pdif=tdif=bdif=0; |
||||
|
||||
switch(mode) |
||||
{ |
||||
case TOP_FIRST_ANALYZE: |
||||
if(top) |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
pdif+=diff(new, ns, new, ns), |
||||
tdif+=diff(new, ns, old, os); |
||||
else |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
pdif+=diff(new, ns, new, ns), |
||||
tdif+=diff(old, os, new, ns); |
||||
break; |
||||
|
||||
case BOTTOM_FIRST_ANALYZE: |
||||
if(top) |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
pdif+=diff(new, ns, new, ns), |
||||
bdif+=diff(old, os, new, ns); |
||||
else |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
pdif+=diff(new, ns, new, ns), |
||||
bdif+=diff(new, ns, old, os); |
||||
break; |
||||
|
||||
case ANALYZE: |
||||
if(top) |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
tdif+=diff(new, ns, old, os), |
||||
bdif+=diff(old, os, new, ns); |
||||
else |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
bdif+=diff(new, ns, old, os), |
||||
tdif+=diff(old, os, new, ns); |
||||
break; |
||||
|
||||
default: /* FULL_ANALYZE */ |
||||
if(top) |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
pdif+=diff(new, ns, new, ns), |
||||
tdif+=diff(new, ns, old, os), |
||||
bdif+=diff(old, os, new, ns); |
||||
else |
||||
for(rend=new+w; new<rend; new++, old++) |
||||
pdif+=diff(new, ns, new, ns), |
||||
bdif+=diff(new, ns, old, os), |
||||
tdif+=diff(old, os, new, ns); |
||||
} |
||||
|
||||
pdiff+=(double)pdif; |
||||
tdiff+=(double)tdif; |
||||
bdiff+=(double)bdif; |
||||
} |
||||
|
||||
scale=1.0/(w*(h-3))/25.0; |
||||
pdiff*=scale; |
||||
tdiff*=scale; |
||||
bdiff*=scale; |
||||
|
||||
if(mode==TOP_FIRST_ANALYZE) |
||||
bdiff=65536.0; |
||||
else if(mode==BOTTOM_FIRST_ANALYZE) |
||||
tdiff=65536.0; |
||||
else if(mode==ANALYZE) |
||||
pdiff=65536.0; |
||||
|
||||
if(bdiff<pdiff && bdiff<tdiff) |
||||
mode=BOTTOM_FIRST; |
||||
else if(tdiff<pdiff && tdiff<bdiff) |
||||
mode=TOP_FIRST; |
||||
else |
||||
mode=PROGRESSIVE; |
||||
} |
||||
|
||||
if( ff_mp_msg_test(MSGT_VFILTER,MSGL_V) ) |
||||
{ |
||||
ff_mp_msg(MSGT_VFILTER, MSGL_INFO, "%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p'); |
||||
if(tdiff==65536.0) ff_mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else ff_mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", tdiff); |
||||
if(bdiff==65536.0) ff_mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else ff_mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", bdiff); |
||||
if(pdiff==65536.0) ff_mp_msg(MSGT_VFILTER, MSGL_INFO," N/A "); else ff_mp_msg(MSGT_VFILTER, MSGL_INFO," %8.2f", pdiff); |
||||
ff_mp_msg(MSGT_VFILTER, MSGL_INFO," \n"); |
||||
} |
||||
|
||||
return mode; |
||||
} |
||||
|
||||
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) |
||||
{ |
||||
mp_image_t *dmpi; |
||||
int w; |
||||
enum mode mode; |
||||
|
||||
if(!(dmpi=ff_vf_get_image(vf->next, mpi->imgfmt, |
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, |
||||
mpi->w, mpi->h))) |
||||
return 0; |
||||
|
||||
w=dmpi->w; |
||||
if(!(dmpi->flags&MP_IMGFLAG_PLANAR)) |
||||
w*=dmpi->bpp/8; |
||||
|
||||
mode=vf->priv->mode; |
||||
|
||||
if(!vf->priv->buf[0]) |
||||
mode=PROGRESSIVE; |
||||
else |
||||
mode=analyze_plane(vf->priv->buf[0], mpi->planes[0], |
||||
w, dmpi->h, w, mpi->stride[0], mode, |
||||
vf->priv->verbose, mpi->fields); |
||||
|
||||
do_plane(dmpi->planes[0], mpi->planes[0], |
||||
w, dmpi->h, |
||||
dmpi->stride[0], mpi->stride[0], |
||||
&vf->priv->buf[0], mode); |
||||
|
||||
if(dmpi->flags&MP_IMGFLAG_PLANAR) |
||||
{ |
||||
do_plane(dmpi->planes[1], mpi->planes[1], |
||||
dmpi->chroma_width, dmpi->chroma_height, |
||||
dmpi->stride[1], mpi->stride[1], |
||||
&vf->priv->buf[1], mode); |
||||
do_plane(dmpi->planes[2], mpi->planes[2], |
||||
dmpi->chroma_width, dmpi->chroma_height, |
||||
dmpi->stride[2], mpi->stride[2], |
||||
&vf->priv->buf[2], mode); |
||||
} |
||||
|
||||
return ff_vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); |
||||
} |
||||
|
||||
static void uninit(struct vf_instance *vf) |
||||
{ |
||||
if (!vf->priv) |
||||
return; |
||||
free(vf->priv->buf[0]); |
||||
free(vf->priv->buf[1]); |
||||
free(vf->priv->buf[2]); |
||||
free(vf->priv); |
||||
} |
||||
|
||||
static int vf_open(vf_instance_t *vf, char *args) |
||||
{ |
||||
vf->put_image = put_image; |
||||
vf->uninit = uninit; |
||||
vf->default_reqs = VFCAP_ACCEPT_STRIDE; |
||||
|
||||
if(!(vf->priv = calloc(1, sizeof(struct vf_priv_s)))) |
||||
{ |
||||
uninit(vf); |
||||
return 0; |
||||
} |
||||
|
||||
vf->priv->mode=AUTO_ANALYZE; |
||||
vf->priv->verbose=0; |
||||
|
||||
while(args && *args) |
||||
{ |
||||
switch(*args) |
||||
{ |
||||
case 't': vf->priv->mode=TOP_FIRST; break; |
||||
case 'a': vf->priv->mode=AUTO; break; |
||||
case 'b': vf->priv->mode=BOTTOM_FIRST; break; |
||||
case 'u': vf->priv->mode=ANALYZE; break; |
||||
case 'T': vf->priv->mode=TOP_FIRST_ANALYZE; break; |
||||
case 'A': vf->priv->mode=AUTO_ANALYZE; break; |
||||
case 'B': vf->priv->mode=BOTTOM_FIRST_ANALYZE; break; |
||||
case 'U': vf->priv->mode=FULL_ANALYZE; break; |
||||
case 'p': vf->priv->mode=PROGRESSIVE; break; |
||||
case 'v': vf->priv->verbose=1; break; |
||||
case ':': break; |
||||
|
||||
default: |
||||
uninit(vf); |
||||
return 0; /* bad args */ |
||||
} |
||||
|
||||
if( (args=strchr(args, ':')) ) args++; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
const vf_info_t ff_vf_info_phase = |
||||
{ |
||||
"phase shift fields", |
||||
"phase", |
||||
"Ville Saari", |
||||
"", |
||||
vf_open, |
||||
NULL |
||||
}; |
Loading…
Reference in new issue