diff options
Diffstat (limited to 'src/post/deinterlace/plugins/vfir.c')
-rw-r--r-- | src/post/deinterlace/plugins/vfir.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/post/deinterlace/plugins/vfir.c b/src/post/deinterlace/plugins/vfir.c new file mode 100644 index 000000000..f60bbecd8 --- /dev/null +++ b/src/post/deinterlace/plugins/vfir.c @@ -0,0 +1,161 @@ +/** + * This file contains code from ffmpeg, see http://ffmpeg.org/ + * + * Originated in imgconvert.c: Misc image convertion routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * + * tvtime port Copyright (C) 2003 Billy Biggs <vektor@dumbterm.net>. + * + * 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, 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 <stdint.h> + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "attributes.h" +#include "xineutils.h" +#include "speedy.h" +#include "deinterlace.h" + +/** + * The MPEG2 spec uses a slightly harsher filter, they specify + * [-1 8 2 8 -1]. ffmpeg uses a similar filter but with more of + * a tendancy to blur than to use the local information. The + * filter taps here are: [-1 4 2 4 -1]. + */ + +static void deinterlace_line( uint8_t *dst, uint8_t *lum_m4, + uint8_t *lum_m3, uint8_t *lum_m2, + uint8_t *lum_m1, uint8_t *lum, int size ) +{ + /** + * C implementation. + int sum; + + for(;size > 0;size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + sum += lum_m1[0] << 2; + sum += -lum[0]; + dst[0] = (sum + 4) >> 3; // This needs to be clipped at 0 and 255: cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + dst++; + } + */ + + mmx_t rounder; + + rounder.uw[0]=4; + rounder.uw[1]=4; + rounder.uw[2]=4; + rounder.uw[3]=4; + pxor_r2r(mm7,mm7); + movq_m2r(rounder,mm6); + + for (;size > 3; size-=4) { + movd_m2r(lum_m4[0],mm0); + movd_m2r(lum_m3[0],mm1); + movd_m2r(lum_m2[0],mm2); + movd_m2r(lum_m1[0],mm3); + movd_m2r(lum[0],mm4); + punpcklbw_r2r(mm7,mm0); + punpcklbw_r2r(mm7,mm1); + punpcklbw_r2r(mm7,mm2); + punpcklbw_r2r(mm7,mm3); + punpcklbw_r2r(mm7,mm4); + paddw_r2r(mm3,mm1); + psllw_i2r(1,mm2); + paddw_r2r(mm4,mm0); + psllw_i2r(2,mm1);// 2 + paddw_r2r(mm6,mm2); + paddw_r2r(mm2,mm1); + psubusw_r2r(mm0,mm1); + psrlw_i2r(3,mm1); // 3 + packuswb_r2r(mm7,mm1); + movd_r2m(mm1,dst[0]); + lum_m4+=4; + lum_m3+=4; + lum_m2+=4; + lum_m1+=4; + lum+=4; + dst+=4; + } + emms(); +} + + +/** + * The commented-out method below that uses the bottom_field member is more + * like the filter as specified in the MPEG2 spec, but it doesn't seem to + * have the desired effect. + */ + +static void deinterlace_scanline_vfir( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + deinterlace_line( output, data->tt1, data->t0, data->m1, data->b0, data->bb1, width*2 ); + // blit_packed422_scanline( output, data->m1, width ); +} + +static void copy_scanline( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->m0, width ); + /* + if( data->bottom_field ) { + deinterlace_line( output, data->tt2, data->t1, data->m2, data->b1, data->bb2, width*2 ); + } else { + deinterlace_line( output, data->tt0, data->t1, data->m0, data->b1, data->bb0, width*2 ); + } + */ +} + + +static deinterlace_method_t vfirmethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "ffmpeg: Vertical Blend", + "Vertical", + 1, + MM_ACCEL_X86_MMXEXT, + 0, + 0, + 0, + 1, + deinterlace_scanline_vfir, + copy_scanline, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void vfir_plugin_init( void ) +#endif +{ + register_deinterlace_method( &vfirmethod ); +} + |