0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00

vf_phase filter by Ville Saari (114263 at foo dot bar dot org)

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@12082 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
rfelker 2004-03-29 04:39:04 +00:00
parent d37c2fad12
commit 9721b82d2d
4 changed files with 332 additions and 1 deletions

View File

@ -3136,6 +3136,52 @@ telecined, inserting this filter before them should make them more reliable.
Currently only libmpeg2 exports the needed flags.
If used on material that does not set them, the filter does nothing.
.TP
.B phase=[t|b|p|a|u|T|B|A|U][:v]
Delay interlaced video by one field time so that the field order
changes.
The intended use is to fix PAL movies that have been captured with the
opposite field order to the film-to-video transfer.
The options are:
.RSs
.IPs t
Capture field order top-first, transfer bottom-first.
Filter will delay the bottom field.
.IPs b
Capture bottom-first, transfer top-first.
Filter will delay the top field.
.IPs p
Capture and transfer with the same field order.
This mode only exists for the documentation of the other options to refer to,
but if you actually select it, the filter will faithfully do nothing ;-)
.IPs a
Capture field order determined automatically by field flags, transfer opposite.
Filter selects among t and b modes on a frame by frame basis using field flags.
If no field information is available, then this works just like u.
.IPs u
Capture unknown or varying, transfer opposite.
Filter selects among t and b on a frame by frame basis by analyzing the
images and selecting the alternative that produces best match between the
fields.
.IPs T
Capture top-first, transfer unknown or varying.
Filter selects among t and p using image analysis.
.IPs B
Capture bottom-first, transfer unknown or varying.
Filter selects among b and p using image analysis.
.IPs A
Capture determined by field flags, transfer unknown or varying.
Filter selects among t, b and p using field flags and image analysis.
If no field information is available, then this works just like U.
This is the default mode.
.IPs U
Both capture and transfer unknown or varying.
Filter selects among t, b and p using image analysis only.
.IPs v
Verbose operation.
Prints the selected mode for each frame and the average squared difference
between fields for t, b, and p alternatives.
.RE
.TP
.B telecine[=start]
Apply 3:2 'telecine' process to increase framerate by 20%.
This most likely will not work correctly with MPlayer, but it can

View File

@ -14,7 +14,7 @@ VIDEO_SRCS_NAT=vd_null.c vd_cinepak.c vd_raw.c vd_hmblck.c vd_fli.c vd_qtrle.c v
VIDEO_SRCS_OPT=vd_realvid.c vd_ffmpeg.c vd_dshow.c vd_dmo.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_zrmjpeg.c vd_xanim.c vd_xvid.c vd_xvid4.c vd_libdv.c vd_qtvideo.c vd_theora.c
VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT)
VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_scale.c vf_format.c vf_noformat.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c vf_fil.c vf_hue.c vf_spp.c vf_yuvcsp.c vf_filmdint.c vf_kerndeint.c vf_rgbtest.c vf_qp.c
VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_scale.c vf_format.c vf_noformat.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c vf_fil.c vf_hue.c vf_spp.c vf_yuvcsp.c vf_filmdint.c vf_kerndeint.c vf_rgbtest.c vf_qp.c vf_phase.c
ifeq ($(HAVE_FFPOSTPROCESS),yes)
VFILTER_SRCS += vf_pp.c
endif

View File

@ -87,6 +87,7 @@ extern vf_info_t vf_info_yuvcsp;
extern vf_info_t vf_info_kerndeint;
extern vf_info_t vf_info_rgbtest;
extern vf_info_t vf_info_qp;
extern vf_info_t vf_info_phase;
// list of available filters:
static vf_info_t* filter_list[]={
@ -167,6 +168,7 @@ static vf_info_t* filter_list[]={
#ifdef USE_LIBAVCODEC
&vf_info_qp,
#endif
&vf_info_phase,
NULL
};

283
libmpcodecs/vf_phase.c Normal file
View File

@ -0,0 +1,283 @@
#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)
{
memcpy(to, mode==(top?BOTTOM_FIRST:TOP_FIRST)?buf:from, w);
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(verbose)
{
printf("%c", mode==BOTTOM_FIRST?'b':mode==TOP_FIRST?'t':'p');
if(tdiff==65536.0) printf(" N/A "); else printf(" %8.2f", tdiff);
if(bdiff==65536.0) printf(" N/A "); else printf(" %8.2f", bdiff);
if(pdiff==65536.0) printf(" N/A "); else printf(" %8.2f", pdiff);
printf(" \n");
}
return mode;
}
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
{
mp_image_t *dmpi;
int w;
enum mode mode;
if(!(dmpi=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 vf_next_put_image(vf, dmpi);
}
static void uninit(struct vf_instance_s* vf)
{
free(vf->priv->buf[0]);
free(vf->priv->buf[1]);
free(vf->priv->buf[2]);
free(vf->priv);
}
static int 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;
}
vf_info_t vf_info_phase =
{
"phase shift fields",
"phase",
"Ville Saari",
"",
open,
NULL
};