diff options
Diffstat (limited to 'libmpcodecs/vf_detc.c')
-rw-r--r-- | libmpcodecs/vf_detc.c | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/libmpcodecs/vf_detc.c b/libmpcodecs/vf_detc.c deleted file mode 100644 index bbc22fca6c..0000000000 --- a/libmpcodecs/vf_detc.c +++ /dev/null @@ -1,458 +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 "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[5]; - int inframes, outframes; - int mode; - int (*analyze)(struct vf_priv_s *, mp_image_t *, mp_image_t *); - int needread; - struct vf_detc_pts_buf ptsbuf; -}; - -#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 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 = 8; x; x--) { - oldp = old++; - newp = new++; - noise = temp = 0; - for (y = 4; 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-7; y += 8) { - for (x = 0; x < w-7; x += 8) { - 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 void 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) -{ - 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) { - /* We need to break at scene changes, but is this a valid test? */ - if ((m.even > p->thres[2]) && (m.odd > p->thres[2]) && (m.temp > p->thres[3]) - && (m.temp > 5*pm.temp) && (m.temp*2 > m.noise)) { - mp_msg(MSGT_VFILTER, MSGL_V, "scene change breaking telecine!\n"); - p->frame = -1; - return TC_DROP; - } - /* Thres. is to compensate for quantization errors when noise is low */ - if (m.noise - m.temp > -p->thres[4]) { - if (COMPARABLE(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.temp < m.odd*m.noise) { - 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]) && (m.even > m.odd) && (m.temp > 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 *vf, mp_image_t *dmpi, double pts) -{ - struct vf_priv_s *p = vf->priv; - int dropflag; - - switch (p->drop) { - default: - 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; - vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); - return 0; - } - - p->outframes++; - return vf_next_put_image(vf, dmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); -} - -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) -{ - 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; - vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); - break; - case TC_PROG: - /* Copy and display the whole frame. */ - copy_image(dmpi, mpi, 2); - ret = do_put_image(vf, dmpi, pts); - 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; - vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); - 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, pts); - if (p->needread) copy_image(dmpi, mpi, 1); - break; - } - return ret; -} - -static int query_format(struct vf_instance *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 *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 *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, "t4", p->thres[4], 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 vf_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] = 440; - p->thres[1] = 720; - p->thres[2] = 2500; - p->thres[3] = 2500; - p->thres[4] = 800; - 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; - vf_detc_init_pts_buf(&p->ptsbuf); - return 1; -} - -const vf_info_t vf_info_detc = { - "de-telecine filter", - "detc", - "Rich Felker", - "", - vf_open, - NULL -}; |