Mercurial > mplayer.hg
changeset 12081:e34700c872ac
vf_phase filter by Ville Saari (114263 at foo dot bar dot org)
author | rfelker |
---|---|
date | Mon, 29 Mar 2004 04:39:04 +0000 |
parents | 1abbfe730adc |
children | f705b0777572 |
files | DOCS/man/en/mplayer.1 libmpcodecs/Makefile libmpcodecs/vf.c libmpcodecs/vf_phase.c |
diffstat | 4 files changed, 332 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1 Sun Mar 28 22:03:37 2004 +0000 +++ b/DOCS/man/en/mplayer.1 Mon Mar 29 04:39:04 2004 +0000 @@ -3136,6 +3136,52 @@ 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
--- a/libmpcodecs/Makefile Sun Mar 28 22:03:37 2004 +0000 +++ b/libmpcodecs/Makefile Mon Mar 29 04:39:04 2004 +0000 @@ -14,7 +14,7 @@ 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
--- a/libmpcodecs/vf.c Sun Mar 28 22:03:37 2004 +0000 +++ b/libmpcodecs/vf.c Mon Mar 29 04:39:04 2004 +0000 @@ -87,6 +87,7 @@ 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 @@ #ifdef USE_LIBAVCODEC &vf_info_qp, #endif + &vf_info_phase, NULL };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpcodecs/vf_phase.c Mon Mar 29 04:39:04 2004 +0000 @@ -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 + };