[Mplayer-cvslog] CVS: 0_90/libmpcodecs vf_detc.c,NONE,1.1 vf_down3dright.c,NONE,1.1 vf_hqdn3d.c,NONE,1.1 vf_telecine.c,NONE,1.1 vf_tfields.c,NONE,1.1

Arpi of Ize arpi at mplayerhq.hu
Mon Mar 10 17:17:04 CET 2003


Update of /cvsroot/mplayer/0_90/libmpcodecs
In directory mail:/var/tmp.root/cvs-serv6305

Added Files:
	vf_detc.c vf_down3dright.c vf_hqdn3d.c vf_telecine.c 
	vf_tfields.c 
Log Message:
backport: new filters


--- NEW FILE ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../config.h"
#include "../mp_msg.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#include "../libvo/fastmemcpy.h"

struct metrics {
	int even;
	int odd;
	int noise;
	int temp;
};

struct vf_priv_s {
	int frame;
	int drop, lastdrop;
	struct metrics pm;
	int thres[4];
	int inframes, outframes;
	int mode;
	int (*analyze)(struct vf_priv_s *, mp_image_t *, mp_image_t *);
	int needread;
};

#define COMPE(a,b,e) (abs((a)-(b)) < (((a)+(b))>>(e)))
#define COMPARABLE(a,b) COMPE((a),(b),2)
#define VERYCLOSE(a,b) COMPE((a),(b),3)

#define OUTER_TC_NBHD(s) ( \
 COMPARABLE((s)[-1].m.even,(s)[-1].m.odd) && \
 COMPARABLE((s)[1].m.even,(s)[0].m.odd) && \
 COMPARABLE((s)[2].m.even,(s)[1].m.odd) && \
 COMPARABLE((s)[-1].m.noise,(s)[0].m.temp) && \
 COMPARABLE((s)[2].m.noise,(s)[2].m.temp) )

#define INNER_TC_NBHD(s,l,h) ( \
 COMPARABLE((s)[0].m.even,(l)) && \
 COMPARABLE((s)[2].m.odd,(l)) && ( \
 COMPARABLE((s)[0].m.noise,(h)) || \
 COMPARABLE((s)[1].m.noise,(h)) ) )

enum {
	TC_DROP,
	TC_PROG,
	TC_IL1,
	TC_IL2
};

static inline void *my_memcpy_pic(void * dst, void * src, int bytesPerLine, int height, int dstStride, int srcStride)
{
	int i;
	void *retval=dst;

	for(i=0; i<height; i++)
	{
		memcpy(dst, src, bytesPerLine);
		src+= srcStride;
		dst+= dstStride;
	}

	return retval;
}

static unsigned int hash_pic(unsigned char *img, int w, int h, int stride)
{
	int step = w*h/1024;
	unsigned int hash=0;
	int x=0, y;

	step -= step % 3;

	for (y=0; y<h; y++) {
		for (; x<w; x+=step) {
			hash = hash ^ (hash<<4) ^ img[x];
		}
		x -= w;
		img += stride;
	}
	
	return hash;
}

static void block_diffs(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns)
{
	int x, y, even=0, odd=0, noise, temp;
	unsigned char *oldp, *newp;
	m->noise = m->temp = 0;
	for (x = 15; x; x--) {
		oldp = old++;
		newp = new++;
		noise = temp = 0;
		for (y = 8; y; y--) {
			even += abs(newp[0]-oldp[0]);
			odd += abs(newp[ns]-oldp[os]);
			noise += newp[ns]-newp[0];
			temp += oldp[os]-newp[0];
			oldp += os<<1;
			newp += ns<<1;
		}
		m->noise += abs(noise);
		m->temp += abs(temp);
	}
	m->even = even;
	m->odd = odd;
}

static void diff_planes(struct metrics *m, unsigned char *old, unsigned char *new, int w, int h, int os, int ns)
{
	int x, y, me=0, mo=0, mn=0, mt=0;
	struct metrics l;
	for (y = 0; y < h-15; y += 16) {
		for (x = 0; x < w-15; x += 16) {
			block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns);
			if (l.even > me) me = l.even;
			if (l.odd > mo) mo = l.odd;
			if (l.noise > mn) mn = l.noise;
			if (l.temp > mt) mt = l.temp;
		}
	}
	m->even = me;
	m->odd = mo;
	m->noise = mn;
	m->temp = mt;
}

static void diff_fields(struct metrics *metr, mp_image_t *old, mp_image_t *new)
{
	struct metrics m, mu, mv;
	diff_planes(&m, old->planes[0], new->planes[0],
		new->w, new->h, old->stride[0], new->stride[0]);
	if (new->flags & MP_IMGFLAG_PLANAR) {
		diff_planes(&mu, old->planes[1], new->planes[1],
			new->chroma_width, new->chroma_height,
			old->stride[1], new->stride[1]);
		diff_planes(&mv, old->planes[2], new->planes[2],
			new->chroma_width, new->chroma_height,
			old->stride[2], new->stride[2]);
		if (mu.even > m.even) m.even = mu.even;
		if (mu.odd > m.odd) m.odd = mu.odd;
		if (mu.noise > m.noise) m.noise = mu.noise;
		if (mu.temp > m.temp) m.temp = mu.temp;
		if (mv.even > m.even) m.even = mv.even;
		if (mv.odd > m.odd) m.odd = mv.odd;
		if (mv.noise > m.noise) m.noise = mv.noise;
		if (mv.temp > m.temp) m.temp = mv.temp;
	}
	*metr = m;
}

static status(int f, struct metrics *m)
{
	mp_msg(MSGT_VFILTER, MSGL_V, "frame %d: e=%d o=%d n=%d t=%d\n",
		f, m->even, m->odd, m->noise, m->temp);
}

static int analyze_fixed_pattern(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old)
{
	if (p->frame >= 0) p->frame = (p->frame+1)%5;
	mp_msg(MSGT_VFILTER, MSGL_V, "frame %d\n", p->frame);
	switch (p->frame) {
	case -1: case 0: case 1: case 2:
		return TC_PROG;
	case 3:
		return TC_IL1;
	case 4:
		return TC_IL2;
	}
	return 0;
}

static int analyze_aggressive(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old)
{
	int i;
	struct metrics m, pm;
	
	if (p->frame >= 0) p->frame = (p->frame+1)%5;
	
	diff_fields(&m, old, new);
	
	status(p->frame, &m);

	pm = p->pm;
	p->pm = m;

	if (p->frame == 4) {
		if (2*m.noise > m.temp) {
			if (VERYCLOSE(m.even, pm.odd)) {
				//mp_msg(MSGT_VFILTER, MSGL_V, "confirmed field match!\n");
				return TC_IL2;
			} else if ((m.even < p->thres[0]) && (m.odd < p->thres[0]) && VERYCLOSE(m.even, m.odd)
				&& VERYCLOSE(m.noise,m.temp) && VERYCLOSE(m.noise,pm.noise)) {
				mp_msg(MSGT_VFILTER, MSGL_V, "interlaced frame appears in duplicate!!!\n");
				p->pm = pm; /* hack :) */
				p->frame = 3;
				return TC_IL1;
			} 
		} else {
			mp_msg(MSGT_VFILTER, MSGL_V, "mismatched telecine fields!\n");
			p->frame = -1;
		}
	}

	if (((2*m.even < m.odd) && (5*m.temp < 4*m.noise))
		|| ((5*m.even < 4*m.odd) && (2*m.temp < m.noise))
		|| (m.even*m.temp < 2*m.odd*m.noise/5) /* ok? */ ) {
		mp_msg(MSGT_VFILTER, MSGL_V, "caught telecine sync!\n");
		p->frame = 3;
		return TC_IL1;
	}

	if (p->frame < 3) {
		if (m.noise > p->thres[3]) {
			if (m.noise > 2*m.temp) {
				mp_msg(MSGT_VFILTER, MSGL_V, "merging fields out of sequence!\n");
				return TC_IL2;
			}
			if ((m.noise > 2*pm.noise) && (m.even > p->thres[2]) && (m.odd > p->thres[2])) {
				mp_msg(MSGT_VFILTER, MSGL_V, "dropping horrible interlaced frame!\n");
				return TC_DROP;
			}
		}
	}

	switch (p->frame) {
	case -1:
		if (4*m.noise > 5*m.temp) {
			mp_msg(MSGT_VFILTER, MSGL_V, "merging fields out of sequence!\n");
			return TC_IL2;
		}
	case 0:
	case 1:
	case 2:
		return TC_PROG;
	case 3:
		if ((m.even > p->thres[1]) && (5*m.even > 4*m.odd) && (5*m.temp > 4*m.noise)) {
			mp_msg(MSGT_VFILTER, MSGL_V, "lost telecine tracking!\n");
			p->frame = -1;
			return TC_PROG;
		}
		return TC_IL1;
	case 4:
		return TC_IL2;
	}
	return 0;
}

static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field)
{
	switch (field) {
	case 0:
		my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
			dmpi->stride[0]*2, mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
		}
		break;
	case 1:
		my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
			mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
			dmpi->stride[0]*2, mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
				mpi->planes[1]+mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
				mpi->planes[2]+mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
		}
		break;
	case 2:
		memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
			dmpi->stride[0], mpi->stride[0]);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			memcpy_pic(dmpi->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height,
				dmpi->stride[1], mpi->stride[1]);
			memcpy_pic(dmpi->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height,
				dmpi->stride[2], mpi->stride[2]);
		}
		break;
	}
}

static int do_put_image(struct vf_instance_s* vf, mp_image_t *dmpi)
{
	struct vf_priv_s *p = vf->priv;
	int dropflag;

	switch (p->drop) {
	case 0:
		dropflag = 0;
		break;
	case 1:
		dropflag = (++p->lastdrop >= 5);
		break;
	case 2:
		dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes);
		break;
	}
	
	if (dropflag) {
		mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n",
			p->outframes, p->inframes, (float)p->outframes/p->inframes);
		p->lastdrop = 0;
		return 0;
	}

	p->outframes++;
	return vf_next_put_image(vf, dmpi);
}

static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
{
	int ret=0;
	mp_image_t *dmpi;
	struct vf_priv_s *p = vf->priv;

	p->inframes++;

	if (p->needread) dmpi = vf_get_image(vf->next, mpi->imgfmt,
		MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
		MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
		mpi->width, mpi->height);
	/* FIXME: is there a good way to get rid of static type? */
	else dmpi = vf_get_image(vf->next, mpi->imgfmt,
		MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
		MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);
		
	switch (p->analyze(p, mpi, dmpi)) {
	case TC_DROP:
		/* Don't copy anything unless we'll need to read it. */
		if (p->needread) copy_image(dmpi, mpi, 2);
		p->lastdrop = 0;
		break;
	case TC_PROG:
		/* Copy and display the whole frame. */
		copy_image(dmpi, mpi, 2);
		ret = do_put_image(vf, dmpi);
		break;
	case TC_IL1:
		/* Only copy bottom field unless we need to read. */
		if (p->needread) copy_image(dmpi, mpi, 2);
		else copy_image(dmpi, mpi, 1);
		p->lastdrop = 0;
		break;
	case TC_IL2:
		/* Copy top field and show frame, then copy bottom if needed. */
		copy_image(dmpi, mpi, 0);
		ret = do_put_image(vf, dmpi);
		if (p->needread) copy_image(dmpi, mpi, 1);
		break;
	}
	return ret;
}

static int query_format(struct vf_instance_s* vf, unsigned int fmt)
{
	/* FIXME - figure out which other formats work */
	switch (fmt) {
	case IMGFMT_YV12:
	case IMGFMT_IYUV:
	case IMGFMT_I420:
		return vf_next_query_format(vf, fmt);
	}
	return 0;
}

static int config(struct vf_instance_s* vf,
        int width, int height, int d_width, int d_height,
	unsigned int flags, unsigned int outfmt)
{
	return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}

static void uninit(struct vf_instance_s* vf)
{
	free(vf->priv);
}

static struct {
	char *name;
	int (*func)(struct vf_priv_s *p, mp_image_t *new, mp_image_t *old);
	int needread;
} anal_funcs[] = {
	{ "fixed", analyze_fixed_pattern, 0 },
	{ "aggressive", analyze_aggressive, 1 },
	{ NULL, NULL, 0 }
};

#define STARTVARS if (0)
#define GETVAR(str, name, out, func) \
 else if (!strncmp((str), name "=", sizeof(name))) \
 (out) = (func)((str) + sizeof(name))

static void parse_var(struct vf_priv_s *p, char *var)
{
	STARTVARS;
	GETVAR(var, "dr", p->drop, atoi);
	GETVAR(var, "t0", p->thres[0], atoi);
	GETVAR(var, "t1", p->thres[1], atoi);
	GETVAR(var, "t2", p->thres[2], atoi);
	GETVAR(var, "t3", p->thres[3], atoi);
	GETVAR(var, "fr", p->frame, atoi);
	GETVAR(var, "am", p->mode, atoi);
}

static void parse_args(struct vf_priv_s *p, char *args)
{
	char *next, *orig;
	for (args=orig=strdup(args); args; args=next) {
		next = strchr(args, ':');
		if (next) *next++ = 0;
		parse_var(p, args);
	}
	free(orig);
}

static int open(vf_instance_t *vf, char* args)
{
	struct vf_priv_s *p;
	vf->config = config;
	vf->put_image = put_image;
	vf->query_format = query_format;
	vf->uninit = uninit;
	vf->default_reqs = VFCAP_ACCEPT_STRIDE;
	vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
	p->frame = -1;
	p->thres[0] = 1760;
	p->thres[1] = 2880;
	p->thres[2] = 10000;
	p->thres[3] = 10000;
	p->drop = 0;
	p->mode = 1;
	if (args) parse_args(p, args);
	p->analyze = anal_funcs[p->mode].func;
	p->needread = anal_funcs[p->mode].needread;
	return 1;
}

vf_info_t vf_info_detc = {
    "de-telecine filter",
    "detc",
    "Rich Felker",
    "",
    open
};



--- NEW FILE ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "../config.h"
#include "../mp_msg.h"
#include "../cpudetect.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#include "../libvo/fastmemcpy.h"
#include "../postproc/rgb2rgb.h"

struct vf_priv_s {
	int skipline;
	int scalew;
	int scaleh;
};

static void toright(unsigned char *dst[3], unsigned char *src[3],
		    unsigned int dststride[3], unsigned int srcstride[3],
		    int w, int h, struct vf_priv_s* p)
{
	int k;

	for (k = 0; k < 3; k++) {
		unsigned char* fromL = src[k];
		unsigned char* fromR = src[k];
		unsigned char* to = dst[k];
		unsigned int src = srcstride[k];
                unsigned int dst = dststride[k];
		unsigned int ss;
		unsigned int dd;
		int i;

		if (k > 0) {
			i = h / 4 - p->skipline / 2;
			ss = src * (h / 4 + p->skipline / 2);
			dd = w / 4;
		} else {
			i = h / 2 - p->skipline;
                        ss = src * (h / 2 + p->skipline);
			dd = w / 2;
		}
		fromR += ss;
		for ( ; i > 0; i--) {
                        int j;
			unsigned char* t = to;
			unsigned char* sL = fromL;
			unsigned char* sR = fromR;

			if (p->scalew == 1) {
				for (j = dd; j > 0; j--)
					*t++ = (*sL++ + *sL++) / 2;
				for (j = dd ; j > 0; j--)
					*t++ = (*sR++ + *sR++) / 2;
			} else {
				for (j = dd * 2 ; j > 0; j--)
					*t++ = *sL++;
				for (j = dd * 2 ; j > 0; j--)
					*t++ = *sR++;
			}
			if (p->scaleh == 1) {
				memcpy(to + dst, to, dst);
                                to += dst;
			}
			to += dst;
			fromL += src;
			fromR += src;
		}
		//printf("K %d  %d   %d   %d  %d \n", k, w, h,  src, dst);
	}
}

static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
{
	mp_image_t *dmpi;

	// hope we'll get DR buffer:
	dmpi=vf_get_image(vf->next, IMGFMT_YV12,
			  MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
			  mpi->w * vf->priv->scalew,
			  mpi->h / vf->priv->scaleh - vf->priv->skipline);

	toright(dmpi->planes, mpi->planes, dmpi->stride,
		mpi->stride, mpi->w, mpi->h, vf->priv);

	return vf_next_put_image(vf,dmpi);
}

static int config(struct vf_instance_s* vf,
		  int width, int height, int d_width, int d_height,
		  unsigned int flags, unsigned int outfmt)
{
	/* FIXME - also support UYVY output? */
	return vf_next_config(vf, width * vf->priv->scalew,
			      height / vf->priv->scaleh - vf->priv->skipline, d_width, d_height, flags, IMGFMT_YV12);
}


static int query_format(struct vf_instance_s* vf, unsigned int fmt)
{
	/* FIXME - really any YUV 4:2:0 input format should work */
	switch (fmt) {
	case IMGFMT_YV12:
	case IMGFMT_IYUV:
	case IMGFMT_I420:
		return vf_next_query_format(vf, IMGFMT_YV12);
	}
	return 0;
}

static void uninit(struct vf_instance_s* vf)
{
	free(vf->priv);
}

static int open(vf_instance_t *vf, char* args)
{
	vf->config=config;
	vf->query_format=query_format;
	vf->put_image=put_image;
	vf->uninit=uninit;

	vf->priv = calloc(1, sizeof (struct vf_priv_s));
	vf->priv->skipline = 0;
	vf->priv->scalew = 1;
	vf->priv->scaleh = 2;
	if (args) sscanf(args, "%d", &vf->priv->skipline);

	return 1;
}

vf_info_t vf_info_down3dright = {
	"convert stereo movie from top-bottom to left-right field",
	"down3dright",
	"Zdenek Kabelac",
	"",
	open
};


--- NEW FILE ---
/*
    Copyright (C) 2003 Daniel Moreno <comac at comac.darktech.org>

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>

#include "../config.h"
#include "../mp_msg.h"

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"
#include "../libvo/fastmemcpy.h"

#define PARAM1_DEFAULT 4.0
#define PARAM2_DEFAULT 3.0
#define PARAM3_DEFAULT 6.0

//===========================================================================//

struct vf_priv_s {
        int Coefs[4][512*16];
        unsigned int *Line;
	unsigned short *Frame[3];
};


/***************************************************************************/

static void uninit(struct vf_instance_s* vf){
	if(vf->priv->Line){free(vf->priv->Line);vf->priv->Line=NULL;}
	if(vf->priv->Frame[0]){free(vf->priv->Frame[0]);vf->priv->Frame[0]=NULL;}
	if(vf->priv->Frame[1]){free(vf->priv->Frame[1]);vf->priv->Frame[1]=NULL;}
	if(vf->priv->Frame[2]){free(vf->priv->Frame[2]);vf->priv->Frame[2]=NULL;}
}

static int config(struct vf_instance_s* vf,
        int width, int height, int d_width, int d_height,
	unsigned int flags, unsigned int outfmt){

	uninit(vf);
        vf->priv->Line = malloc(width*sizeof(int));

	return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}

static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
//    int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
    int dMul= PrevMul-CurrMul;
    int d=((dMul+0x10007FF)/(65536/16));
    return CurrMul + Coef[d];
}

static void deNoise(unsigned char *Frame,        // mpi->planes[x]
                    unsigned char *FrameDest,    // dmpi->planes[x]
                    unsigned int *LineAnt,      // vf->priv->Line (width bytes)
		    unsigned short **FrameAntPtr,
                    int W, int H, int sStride, int dStride,
                    int *Horizontal, int *Vertical, int *Temporal)
{
    int X, Y;
    int sLineOffs = 0, dLineOffs = 0;
    unsigned int PixelAnt;
    int PixelDst;
    unsigned short* FrameAnt=(*FrameAntPtr);
    
    if(!FrameAnt){
	(*FrameAntPtr)=FrameAnt=malloc(W*H*sizeof(unsigned short));
	for (Y = 0; Y < H; Y++){
	    unsigned short* dst=&FrameAnt[Y*W];
	    unsigned char* src=Frame+Y*sStride;
	    for (X = 0; X < W; X++) dst[X]=src[X]<<8;
	}
    }

    /* First pixel has no left nor top neightbour. Only previous frame */
    LineAnt[0] = PixelAnt = Frame[0]<<16;
    PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal);
    FrameAnt[0] = ((PixelDst+0x1000007F)/256);
    FrameDest[0]= ((PixelDst+0x10007FFF)/65536);

    /* Fist line has no top neightbour. Only left one for each pixel and
     * last frame */
    for (X = 1; X < W; X++){
        LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
        PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal);
	FrameAnt[X] = ((PixelDst+0x1000007F)/256);
	FrameDest[X]= ((PixelDst+0x10007FFF)/65536);
    }

    for (Y = 1; Y < H; Y++){
	unsigned int PixelAnt;
	unsigned short* LinePrev=&FrameAnt[Y*W];
	sLineOffs += sStride, dLineOffs += dStride;
        /* First pixel on each line doesn't have previous pixel */
        PixelAnt = Frame[sLineOffs]<<16;
        LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
	PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
	LinePrev[0] = ((PixelDst+0x1000007F)/256);
	FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)/65536);

        for (X = 1; X < W; X++){
	    int PixelDst;
            /* The rest are normal */
            PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
            LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
	    PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal);
	    LinePrev[X] = ((PixelDst+0x1000007F)/256);
	    FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)/65536);
        }
    }
}


static int put_image(struct vf_instance_s* vf, mp_image_t *mpi){
	int cw= mpi->w >> mpi->chroma_x_shift;
	int ch= mpi->h >> mpi->chroma_y_shift;
        int W = mpi->w, H = mpi->h;

	mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
		MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
                mpi->w,mpi->h);

	if(!dmpi) return 0;

        deNoise(mpi->planes[0], dmpi->planes[0],
		vf->priv->Line, &vf->priv->Frame[0], W, H,
                mpi->stride[0], dmpi->stride[0],
                vf->priv->Coefs[0],
                vf->priv->Coefs[0],
                vf->priv->Coefs[1]);
        deNoise(mpi->planes[1], dmpi->planes[1],
		vf->priv->Line, &vf->priv->Frame[1], cw, ch,
                mpi->stride[1], dmpi->stride[1],
                vf->priv->Coefs[2],
                vf->priv->Coefs[2],
                vf->priv->Coefs[3]);
        deNoise(mpi->planes[2], dmpi->planes[2],
		vf->priv->Line, &vf->priv->Frame[2], cw, ch,
                mpi->stride[2], dmpi->stride[2],
                vf->priv->Coefs[2],
                vf->priv->Coefs[2],
                vf->priv->Coefs[3]);

	return vf_next_put_image(vf,dmpi);
}

//===========================================================================//

static int query_format(struct vf_instance_s* vf, unsigned int fmt){
        switch(fmt)
	{
	case IMGFMT_YV12:
	case IMGFMT_I420:
	case IMGFMT_IYUV:
	case IMGFMT_YVU9:
	case IMGFMT_444P:
	case IMGFMT_422P:
	case IMGFMT_411P:
		return vf_next_query_format(vf, fmt);
	}
	return 0;
}


#define ABS(A) ( (A) > 0 ? (A) : -(A) )

static void PrecalcCoefs(int *Ct, double Dist25)
{
    int i;
    double Gamma, Simil, C;

    Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001);

    for (i = -256*16; i < 256*16; i++)
    {
        Simil = 1.0 - ABS(i) / (16*255.0);
        C = pow(Simil, Gamma) * 65536.0 * (double)i / 16.0;
        Ct[16*256+i] = (C<0) ? (C-0.5) : (C+0.5);
    }
}


static int open(vf_instance_t *vf, char* args){
        double LumSpac, LumTmp, ChromSpac, ChromTmp;
        double Param1, Param2, Param3, Param4;

	vf->config=config;
	vf->put_image=put_image;
        vf->query_format=query_format;
        vf->uninit=uninit;
	vf->priv=malloc(sizeof(struct vf_priv_s));
        memset(vf->priv, 0, sizeof(struct vf_priv_s));

        if (args)
        {
            switch(sscanf(args, "%lf:%lf:%lf:%lf",
                          &Param1, &Param2, &Param3, &Param4
                         ))
            {
            case 0:
                LumSpac = PARAM1_DEFAULT;
                LumTmp = PARAM3_DEFAULT;

                ChromSpac = PARAM2_DEFAULT;
                ChromTmp = LumTmp * ChromSpac / LumSpac;
                break;

            case 1:
                LumSpac = Param1;
                LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;

                ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
                ChromTmp = LumTmp * ChromSpac / LumSpac;
                break;

            case 2:
                LumSpac = Param1;
                LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;

                ChromSpac = Param2;
                ChromTmp = LumTmp * ChromSpac / LumSpac;
                break;

            case 3:
                LumSpac = Param1;
                LumTmp = Param3;

                ChromSpac = Param2;
                ChromTmp = LumTmp * ChromSpac / LumSpac;
                break;

            case 4:
                LumSpac = Param1;
                LumTmp = Param3;

                ChromSpac = Param2;
                ChromTmp = Param4;
                break;

            default:
                LumSpac = PARAM1_DEFAULT;
                LumTmp = PARAM3_DEFAULT;

                ChromSpac = PARAM2_DEFAULT;
                ChromTmp = LumTmp * ChromSpac / LumSpac;
            }
        }
        else
        {
            LumSpac = PARAM1_DEFAULT;
            LumTmp = PARAM3_DEFAULT;

            ChromSpac = PARAM2_DEFAULT;
            ChromTmp = LumTmp * ChromSpac / LumSpac;
        }

        PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
        PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
        PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
        PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);

	return 1;
}

vf_info_t vf_info_hqdn3d = {
    "High Quality 3D Denoiser",
    "hqdn3d",
    "Daniel Moreno & A'rpi",
    "",
    open
};

//===========================================================================//

--- NEW FILE ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../config.h"
#include "../mp_msg.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#include "../libvo/fastmemcpy.h"

struct vf_priv_s {
	int frame;
};

static inline void *my_memcpy_pic(void * dst, void * src, int bytesPerLine, int height, int dstStride, int srcStride)
{
	int i;
	void *retval=dst;

	for(i=0; i<height; i++)
	{
		memcpy(dst, src, bytesPerLine);
		src+= srcStride;
		dst+= dstStride;
	}

	return retval;
}

static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
{
	mp_image_t *dmpi;
	int ret;

	vf->priv->frame = (vf->priv->frame+1)%4;
	
	dmpi = vf_get_image(vf->next, mpi->imgfmt,
		MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
		MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);

	ret = 0;
	//    0/0  1/1  2/2  2/3  3/0
	switch (vf->priv->frame) {
	case 0:
		my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
			mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
			dmpi->stride[0]*2, mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
				mpi->planes[1]+mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
				mpi->planes[2]+mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
		}
		ret = vf_next_put_image(vf, dmpi);
	case 1:
	case 2:
		memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
			dmpi->stride[0], mpi->stride[0]);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			memcpy_pic(dmpi->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height,
				dmpi->stride[1], mpi->stride[1]);
			memcpy_pic(dmpi->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height,
				dmpi->stride[2], mpi->stride[2]);
		}
		return vf_next_put_image(vf, dmpi) || ret;
	case 3:
		my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
			mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2,
			dmpi->stride[0]*2, mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
				mpi->planes[1]+mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
				mpi->planes[2]+mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
		}
		ret = vf_next_put_image(vf, dmpi);
		my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
			dmpi->stride[0]*2, mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
		}
		return ret;
	}
	return 0;
}

static int query_format(struct vf_instance_s* vf, unsigned int fmt)
{
	/* FIXME - figure out which other formats work */
	switch (fmt) {
	case IMGFMT_YV12:
	case IMGFMT_IYUV:
	case IMGFMT_I420:
		return vf_next_query_format(vf, fmt);
	}
	return 0;
}

static int config(struct vf_instance_s* vf,
        int width, int height, int d_width, int d_height,
	unsigned int flags, unsigned int outfmt)
{
	return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}

static void uninit(struct vf_instance_s* vf)
{
	free(vf->priv);
}

static int open(vf_instance_t *vf, char* args)
{
	//vf->config = config;
	vf->put_image = put_image;
	//vf->query_format = query_format;
	vf->uninit = uninit;
	vf->default_reqs = VFCAP_ACCEPT_STRIDE;
	vf->priv = calloc(1, sizeof(struct vf_priv_s));
	vf->priv->frame = 1;
	if (args) sscanf(args, "%d", &vf->priv->frame);
	vf->priv->frame--;
	return 1;
}

vf_info_t vf_info_telecine = {
    "telecine filter",
    "telecine",
    "Rich Felker",
    "",
    open
};



--- NEW FILE ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../config.h"
#include "../mp_msg.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#include "../libvo/fastmemcpy.h"

struct vf_priv_s {
	int mode;
};

static inline void *my_memcpy_pic(void * dst, void * src, int bytesPerLine, int height, int dstStride, int srcStride)
{
	int i;
	void *retval=dst;

	for(i=0; i<height; i++)
	{
		memcpy(dst, src, bytesPerLine);
		src+= srcStride;
		dst+= dstStride;
	}

	return retval;
}

static void deint(unsigned char *dest, int ds, unsigned char *src, int ss, int w, int h, int field)
{
	int x, y;
	src += ss;
	dest += ds;
	if (field) {
		src += ss;
		dest += ds;
		h -= 2;
	}
	for (y=h/2; y; y--) {
		for (x=0; x<w; x++) {
			if (((src[x-ss] < src[x]) && (src[x+ss] < src[x])) ||
				((src[x-ss] > src[x]) && (src[x+ss] > src[x]))) {
				//dest[x] = (src[x+ss] + src[x-ss])>>1;
				dest[x] = ((src[x+ss]<<1) + (src[x-ss]<<1)
					+ src[x+ss+1] + src[x-ss+1]
					+ src[x+ss-1] + src[x-ss-1])>>3;
			}
			else dest[x] = src[x];
		}
		dest += ds<<1;
		src += ss<<1;
	}
}



static int put_image(struct vf_instance_s* vf, mp_image_t *mpi)
{
	int ret;
	mp_image_t *dmpi;

	switch (vf->priv->mode) {
	case 0:
		dmpi = vf_get_image(vf->next, mpi->imgfmt,
			MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
			mpi->width, mpi->height/2);
		memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
			dmpi->stride[0], mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			memcpy_pic(dmpi->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1], mpi->stride[1]*2);
			memcpy_pic(dmpi->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2], mpi->stride[2]*2);
		}
		ret = vf_next_put_image(vf, dmpi);
		
		memcpy_pic(dmpi->planes[0], mpi->planes[0] + mpi->stride[0],
			mpi->w, mpi->h/2, dmpi->stride[0], mpi->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			memcpy_pic(dmpi->planes[1], mpi->planes[1] + mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1], mpi->stride[1]*2);
			memcpy_pic(dmpi->planes[2], mpi->planes[2] + mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2], mpi->stride[2]*2);
		}
		return vf_next_put_image(vf, dmpi) || ret;
	case 1:
		dmpi = vf_get_image(vf->next, mpi->imgfmt,
			MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
			mpi->width, mpi->height);
		my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
			dmpi->stride[0]*2, mpi->stride[0]*2);
		deint(dmpi->planes[0], dmpi->stride[0], mpi->planes[0], mpi->stride[0], mpi->w, mpi->h, 0);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
			deint(dmpi->planes[1], dmpi->stride[1], mpi->planes[1], mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height, 0);
			deint(dmpi->planes[2], dmpi->stride[2], mpi->planes[2], mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height, 0);
		}
		ret = vf_next_put_image(vf, dmpi);
		
		my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0], mpi->planes[0] + mpi->stride[0],
			mpi->w, mpi->h/2, dmpi->stride[0]*2, mpi->stride[0]*2);
		deint(dmpi->planes[0], dmpi->stride[0], mpi->planes[0], mpi->stride[0], mpi->w, mpi->h, 1);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1], mpi->planes[1] + mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, mpi->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2], mpi->planes[2] + mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, mpi->stride[2]*2);
			deint(dmpi->planes[1], dmpi->stride[1], mpi->planes[1], mpi->stride[1],
				mpi->chroma_width, mpi->chroma_height, 1);
			deint(dmpi->planes[2], dmpi->stride[2], mpi->planes[2], mpi->stride[2],
				mpi->chroma_width, mpi->chroma_height, 1);
		}
		return vf_next_put_image(vf, dmpi) || ret;
	}
	return 0;
}

static int query_format(struct vf_instance_s* vf, unsigned int fmt)
{
	/* FIXME - figure out which other formats work */
	switch (fmt) {
	case IMGFMT_YV12:
	case IMGFMT_IYUV:
	case IMGFMT_I420:
		return vf_next_query_format(vf, fmt);
	}
	return 0;
}

static int config(struct vf_instance_s* vf,
        int width, int height, int d_width, int d_height,
	unsigned int flags, unsigned int outfmt)
{
	switch (vf->priv->mode) {
	case 0:
		return vf_next_config(vf,width,height/2,d_width,d_height,flags,outfmt);
	case 1:
		return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
	}
	return 0;
}

static void uninit(struct vf_instance_s* vf)
{
	free(vf->priv);
}

static int open(vf_instance_t *vf, char* args)
{
	struct vf_priv_s *p;
	vf->config = config;
	vf->put_image = put_image;
	vf->query_format = query_format;
	vf->uninit = uninit;
	vf->default_reqs = VFCAP_ACCEPT_STRIDE;
	vf->priv = p = calloc(1, sizeof(struct vf_priv_s));
	vf->priv->mode = 0;
	if (args) sscanf(args, "%d", &vf->priv->mode);
	return 1;
}

vf_info_t vf_info_tfields = {
    "temporal field separation",
    "tfields",
    "Rich Felker",
    "",
    open
};





More information about the MPlayer-cvslog mailing list