diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2003-06-13 01:48:09 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2003-06-13 01:48:09 +0000 |
commit | d349cabadd8f4b3530a9ae7049faa3f11387eab8 (patch) | |
tree | 8d6e84bc870bc7473ea55e18bf3b58062251c59d /src/post/deinterlace/plugins | |
parent | a6b05cacbf52dd3b3b7aa4974d81e2221e203097 (diff) | |
download | xine-lib-d349cabadd8f4b3530a9ae7049faa3f11387eab8.tar.gz xine-lib-d349cabadd8f4b3530a9ae7049faa3f11387eab8.tar.bz2 |
new deinterlacer plugin based on tvtime
(please report if compilation breaks on non-x86 plataform)
see xine-devel for more information
CVS patchset: 5032
CVS date: 2003/06/13 01:48:09
Diffstat (limited to 'src/post/deinterlace/plugins')
-rw-r--r-- | src/post/deinterlace/plugins/Makefile.am | 22 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/double.c | 65 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/greedy.c | 195 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/greedy2frame.c | 198 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/linear.c | 63 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/linearblend.c | 180 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/plugins.h | 52 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/vfir.c | 161 | ||||
-rw-r--r-- | src/post/deinterlace/plugins/weave.c | 65 |
9 files changed, 1001 insertions, 0 deletions
diff --git a/src/post/deinterlace/plugins/Makefile.am b/src/post/deinterlace/plugins/Makefile.am new file mode 100644 index 000000000..65e430134 --- /dev/null +++ b/src/post/deinterlace/plugins/Makefile.am @@ -0,0 +1,22 @@ +include $(top_srcdir)/misc/Makefile.common + +AM_CPPFLAGS = -I../ + +EXTRA_DIST = + +libdir = $(XINE_PLUGINDIR)/post + +noinst_LTLIBRARIES = libdeinterlaceplugins.la + +libdeinterlaceplugins_la_SOURCES = \ + double.c \ + greedy.c \ + linear.c \ + linearblend.c \ + vfir.c \ + weave.c \ + greedy2frame.c +libdeinterlaceplugins_la_LIBADD = $(XINE_LIB) +libdeinterlaceplugins_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + +noinst_HEADERS = plugins.h diff --git a/src/post/deinterlace/plugins/double.c b/src/post/deinterlace/plugins/double.c new file mode 100644 index 000000000..f39e1ddfc --- /dev/null +++ b/src/post/deinterlace/plugins/double.c @@ -0,0 +1,65 @@ +/** + * Line doubler deinterlacing plugin. + * + * Copyright (C) 2002 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> +#include "speedy.h" +#include "deinterlace.h" + +static void deinterlace_scanline_double( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->t0, width ); +} + +static void copy_scanline( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->m0, width ); +} + + +static deinterlace_method_t doublemethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "Line Doubler", + "LineDoubler", + 1, + 0, + 0, + 0, + 0, + 1, + deinterlace_scanline_double, + copy_scanline, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void double_plugin_init( void ) +#endif +{ + register_deinterlace_method( &doublemethod ); +} + diff --git a/src/post/deinterlace/plugins/greedy.c b/src/post/deinterlace/plugins/greedy.c new file mode 100644 index 000000000..fb7eb454c --- /dev/null +++ b/src/post/deinterlace/plugins/greedy.c @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2000 Tom Barry All rights reserved. + * mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>. + * + * This code is ported from DScaler: http://deinterlace.sf.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 "deinterlace.h" +#include "speedtools.h" +#include "speedy.h" + +// This is a simple lightweight DeInterlace method that uses little CPU time +// but gives very good results for low or intermedite motion. +// It defers frames by one field, but that does not seem to produce noticeable +// lip sync problems. +// +// The method used is to take either the older or newer weave pixel depending +// upon which give the smaller comb factor, and then clip to avoid large damage +// when wrong. +// +// I'd intended this to be part of a larger more elaborate method added to +// Blended Clip but this give too good results for the CPU to ignore here. + +static void copy_scanline( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->m1, width ); +} + +static int GreedyMaxComb = 15; + +static void deinterlace_greedy_packed422_scanline_mmxext( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ +#ifdef ARCH_X86 + mmx_t MaxComb; + uint8_t *m0 = data->m0; + uint8_t *t1 = data->t1; + uint8_t *b1 = data->b1; + uint8_t *m2 = data->m2; + + // How badly do we let it weave? 0-255 + MaxComb.ub[ 0 ] = GreedyMaxComb; + MaxComb.ub[ 1 ] = GreedyMaxComb; + MaxComb.ub[ 2 ] = GreedyMaxComb; + MaxComb.ub[ 3 ] = GreedyMaxComb; + MaxComb.ub[ 4 ] = GreedyMaxComb; + MaxComb.ub[ 5 ] = GreedyMaxComb; + MaxComb.ub[ 6 ] = GreedyMaxComb; + MaxComb.ub[ 7 ] = GreedyMaxComb; + + // L2 == m0 + // L1 == t1 + // L3 == b1 + // LP2 == m2 + + width /= 4; + while( width-- ) { + movq_m2r( *t1, mm1 ); // L1 + movq_m2r( *m0, mm2 ); // L2 + movq_m2r( *b1, mm3 ); // L3 + movq_m2r( *m2, mm0 ); // LP2 + + // average L1 and L3 leave result in mm4 + movq_r2r( mm1, mm4 ); // L1 + pavgb_r2r( mm3, mm4 ); // (L1 + L3)/2 + + + // get abs value of possible L2 comb + movq_r2r( mm2, mm7 ); // L2 + psubusb_r2r( mm4, mm7 ); // L2 - avg + movq_r2r( mm4, mm5 ); // avg + psubusb_r2r( mm2, mm5 ); // avg - L2 + por_r2r( mm7, mm5 ); // abs(avg-L2) + movq_r2r( mm4, mm6 ); // copy of avg for later + + + // get abs value of possible LP2 comb + movq_r2r( mm0, mm7 ); // LP2 + psubusb_r2r( mm4, mm7 ); // LP2 - avg + psubusb_r2r( mm0, mm4 ); // avg - LP2 + por_r2r( mm7, mm4 ); // abs(avg-LP2) + + // use L2 or LP2 depending upon which makes smaller comb + psubusb_r2r( mm5, mm4 ); // see if it goes to zero + psubusb_r2r( mm5, mm5 ); // 0 + pcmpeqb_r2r( mm5, mm4 ); // if (mm4=0) then FF else 0 + pcmpeqb_r2r( mm4, mm5 ); // opposite of mm4 + + // if Comb(LP2) <= Comb(L2) then mm4=ff, mm5=0 else mm4=0, mm5 = 55 + pand_r2r( mm2, mm5 ); // use L2 if mm5 == ff, else 0 + pand_r2r( mm0, mm4 ); // use LP2 if mm4 = ff, else 0 + por_r2r( mm5, mm4 ); // may the best win + + // Now lets clip our chosen value to be not outside of the range + // of the high/low range L1-L3 by more than abs(L1-L3) + // This allows some comb but limits the damages and also allows more + // detail than a boring oversmoothed clip. + + movq_r2r( mm1, mm2 ); // copy L1 + psubusb_r2r( mm3, mm2 ); // - L3, with saturation + paddusb_r2r( mm3, mm2 ); // now = Max(L1,L3) + + pcmpeqb_r2r( mm7, mm7 ); // all ffffffff + psubusb_r2r( mm1, mm7 ); // - L1 + paddusb_r2r( mm7, mm3 ); // add, may sat at fff.. + psubusb_r2r( mm7, mm3 ); // now = Min(L1,L3) + + // allow the value to be above the high or below the low by amt of MaxComb + paddusb_m2r( MaxComb, mm2 ); // increase max by diff + psubusb_m2r( MaxComb, mm3 ); // lower min by diff + + psubusb_r2r( mm3, mm4 ); // best - Min + paddusb_r2r( mm3, mm4 ); // now = Max(best,Min(L1,L3) + + pcmpeqb_r2r( mm7, mm7 ); // all ffffffff + psubusb_r2r( mm4, mm7 ); // - Max(best,Min(best,L3) + paddusb_r2r( mm7, mm2 ); // add may sat at FFF.. + psubusb_r2r( mm7, mm2 ); // now = Min( Max(best, Min(L1,L3), L2 )=L2 clipped + + movntq_r2m( mm2, *output ); // move in our clipped best + + // Advance to the next set of pixels. + output += 8; + m0 += 8; + t1 += 8; + b1 += 8; + m2 += 8; + } + sfence(); + emms(); +#endif +} + +static deinterlace_setting_t settings[] = +{ + { + "Greedy Max Comb", + SETTING_SLIDER, + &GreedyMaxComb, + 15, 0, 255, 1, + 0 + } +}; + +static deinterlace_method_t greedymethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "DScaler: Greedy - Low motion", + "Greedy", + 3, + MM_ACCEL_X86_MMXEXT, + 0, + 1, + settings, + 1, + copy_scanline, + deinterlace_greedy_packed422_scanline_mmxext, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void greedy_plugin_init( void ) +#endif +{ + register_deinterlace_method( &greedymethod ); +} + diff --git a/src/post/deinterlace/plugins/greedy2frame.c b/src/post/deinterlace/plugins/greedy2frame.c new file mode 100644 index 000000000..00c9b34cb --- /dev/null +++ b/src/post/deinterlace/plugins/greedy2frame.c @@ -0,0 +1,198 @@ +/** + * Copyright (c) 2000 John Adcock, Tom Barry, Steve Grimm All rights reserved. + * mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>. + * + * This code is ported from DScaler: http://deinterlace.sf.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 "deinterlace.h" +#include "speedtools.h" +#include "speedy.h" + +static int GreedyTwoFrameThreshold = 4; +static int GreedyTwoFrameThreshold2 = 8; + +static void deinterlace_greedytwoframe_packed422_scanline_mmxext( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ +#ifdef ARCH_X86 + const mmx_t Mask = { 0x7f7f7f7f7f7f7f7fULL }; + const mmx_t DwordOne = { 0x0000000100000001ULL }; + const mmx_t DwordTwo = { 0x0000000200000002ULL }; + mmx_t qwGreedyTwoFrameThreshold; + uint8_t *m0 = data->m0; + uint8_t *t1 = data->t1; + uint8_t *b1 = data->b1; + uint8_t *m2 = data->m2; + uint8_t *t3 = data->t1; + uint8_t *b3 = data->b1; + + qwGreedyTwoFrameThreshold.b[ 0 ] = GreedyTwoFrameThreshold; + qwGreedyTwoFrameThreshold.b[ 1 ] = GreedyTwoFrameThreshold2; + qwGreedyTwoFrameThreshold.b[ 2 ] = GreedyTwoFrameThreshold; + qwGreedyTwoFrameThreshold.b[ 4 ] = GreedyTwoFrameThreshold; + qwGreedyTwoFrameThreshold.b[ 6 ] = GreedyTwoFrameThreshold; + + width /= 4; + while( width-- ) { + movq_m2r( *m0, mm0 ); + movq_m2r( *t1, mm1 ); + movq_m2r( *b1, mm3 ); + movq_m2r( *m2, mm2 ); + + // Average T1 and B1 so we can do interpolated bobbing if we bob onto T1. + movq_r2r( mm3, mm7 ); // mm7 = B1 + pavgb_r2r( mm1, mm7 ); + + // calculate |M1-M0| put result in mm4 need to keep mm0 intact + // if we have a good processor then make mm0 the average of M1 and M0 + // which should make weave look better when there is small amounts of + // movement + movq_r2r( mm0, mm4 ); + movq_r2r( mm2, mm5 ); + psubusb_r2r( mm2, mm4 ); + psubusb_r2r( mm0, mm5 ); + por_r2r( mm5, mm4 ); + psrlw_i2r( 1, mm4 ); + pavgb_r2r( mm2, mm0 ); + pand_r2r( mm6, mm4 ); + + // if |M1-M0| > Threshold we want dword worth of twos + pcmpgtb_m2r( qwGreedyTwoFrameThreshold, mm4 ); + pand_m2r( Mask, mm4 ); // get rid of any sign bit + pcmpgtd_m2r( DwordOne, mm4 ); // do we want to bob + pandn_m2r( DwordTwo, mm4 ); + + movq_m2r( *t3, mm2 ); // mm2 = T0 + + // calculate |T1-T0| put result in mm5 + movq_r2r( mm2, mm5 ); + psubusb_r2r( mm1, mm5 ); + psubusb_r2r( mm2, mm1 ); + por_r2r( mm1, mm5 ); + psrlw_i2r( 1, mm5 ); + pand_r2r( mm6, mm5 ); + + // if |T1-T0| > Threshold we want dword worth of ones + pcmpgtb_m2r( qwGreedyTwoFrameThreshold, mm5 ); + pand_r2r( mm6, mm5 ); // get rid of any sign bit + pcmpgtd_m2r( DwordOne, mm5 ); + pandn_m2r( DwordOne, mm5 ); + paddd_r2r( mm5, mm4 ); + + movq_m2r( *b3, mm2 ); // B0 + + // calculate |B1-B0| put result in mm5 + movq_r2r( mm2, mm5 ); + psubusb_r2r( mm3, mm5 ); + psubusb_r2r( mm2, mm3 ); + por_r2r( mm3, mm5 ); + psrlw_i2r( 1, mm5 ); + pand_r2r( mm6, mm5 ); + + // if |B1-B0| > Threshold we want dword worth of ones + pcmpgtb_m2r( qwGreedyTwoFrameThreshold, mm5 ); + pand_r2r( mm6, mm5 ); // get rid of any sign bit + pcmpgtd_m2r( DwordOne, mm5 ); + pandn_m2r( DwordOne, mm5 ); + paddd_r2r( mm5, mm4 ); + + pcmpgtd_m2r( DwordTwo, mm4 ); + + movq_r2r( mm4, mm5 ); + // mm4 now is 1 where we want to weave and 0 where we want to bob + pand_r2r( mm0, mm4 ); + pandn_r2r( mm7, mm5 ); + por_r2r( mm5, mm4 ); + + movq_r2m( mm4, *output ); + + // Advance to the next set of pixels. + output += 8; + m0 += 8; + t1 += 8; + b1 += 8; + m2 += 8; + t3 += 8; + b3 += 8; + } + sfence(); + emms(); +#endif +} + +static void copy_scanline( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->m1, width ); +} + + +static deinterlace_setting_t settings[] = +{ + { + "Greedy 2 Frame Luma Threshold", + SETTING_SLIDER, + &GreedyTwoFrameThreshold, + 4, 0, 128, 1, + 0 + }, + { + "Greedy 2 Frame Chroma Threshold", + SETTING_SLIDER, + &GreedyTwoFrameThreshold2, + 8, 0, 128, 1, + 0 + } +}; + +static deinterlace_method_t greedymethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "Greedy - 2-frame (DScaler)", + "Greedy2Frame", + 4, + MM_ACCEL_X86_MMXEXT, + 0, + 2, + settings, + 1, + copy_scanline, + deinterlace_greedytwoframe_packed422_scanline_mmxext, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void greedy2frame_plugin_init( void ) +#endif +{ + register_deinterlace_method( &greedymethod ); +} + diff --git a/src/post/deinterlace/plugins/linear.c b/src/post/deinterlace/plugins/linear.c new file mode 100644 index 000000000..1e84fb722 --- /dev/null +++ b/src/post/deinterlace/plugins/linear.c @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2002 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> +#include "speedy.h" +#include "deinterlace.h" + +static void deinterlace_scanline_linear( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + interpolate_packed422_scanline( output, data->t0, data->b0, width ); +} + +static void copy_scanline( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->m0, width ); +} + + +static deinterlace_method_t linearmethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "Linear Interpolation", + "Linear", + 1, + 0, + 0, + 0, + 0, + 1, + deinterlace_scanline_linear, + copy_scanline, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void linear_plugin_init( void ) +#endif +{ + register_deinterlace_method( &linearmethod ); +} + diff --git a/src/post/deinterlace/plugins/linearblend.c b/src/post/deinterlace/plugins/linearblend.c new file mode 100644 index 000000000..1da84c24b --- /dev/null +++ b/src/post/deinterlace/plugins/linearblend.c @@ -0,0 +1,180 @@ +/** + * Linear blend deinterlacing plugin. The algorithm for this filter is based + * on the mythtv sources, which took it from the mplayer sources. + * + * The file is postprocess_template.c in mplayer, and is + * + * Copyright (C) 2001-2002 Michael Niedermayer (michaelni@gmx.at) + * + * 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 <stdint.h> + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "attributes.h" +#include "xineutils.h" +#include "speedtools.h" +#include "speedy.h" +#include "deinterlace.h" + +static void deinterlace_scanline_linear_blend( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ +#ifdef ARCH_X86 + uint8_t *t0 = data->t0; + uint8_t *b0 = data->b0; + uint8_t *m1 = data->m1; + int i; + + // Get width in bytes. + width *= 2; + i = width / 8; + width -= i * 8; + + pxor_r2r( mm7, mm7 ); + while( i-- ) { + movd_m2r( *t0, mm0 ); + movd_m2r( *b0, mm1 ); + movd_m2r( *m1, mm2 ); + + movd_m2r( *(t0+4), mm3 ); + movd_m2r( *(b0+4), mm4 ); + movd_m2r( *(m1+4), mm5 ); + + punpcklbw_r2r( mm7, mm0 ); + punpcklbw_r2r( mm7, mm1 ); + punpcklbw_r2r( mm7, mm2 ); + + punpcklbw_r2r( mm7, mm3 ); + punpcklbw_r2r( mm7, mm4 ); + punpcklbw_r2r( mm7, mm5 ); + + psllw_i2r( 1, mm2 ); + psllw_i2r( 1, mm5 ); + paddw_r2r( mm0, mm2 ); + paddw_r2r( mm3, mm5 ); + paddw_r2r( mm1, mm2 ); + paddw_r2r( mm4, mm5 ); + psrlw_i2r( 2, mm2 ); + psrlw_i2r( 2, mm5 ); + packuswb_r2r( mm2, mm2 ); + packuswb_r2r( mm5, mm5 ); + + movd_r2m( mm2, *output ); + movd_r2m( mm5, *(output+4) ); + output += 8; + t0 += 8; + b0 += 8; + m1 += 8; + } + while( width-- ) { + *output++ = (*t0++ + *b0++ + (2 * *m1++))>>2; + } + sfence(); + emms(); +#endif +} + +static void deinterlace_scanline_linear_blend2( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ +#ifdef ARCH_X86 + uint8_t *m0 = data->m0; + uint8_t *t1 = data->t1; + uint8_t *b1 = data->b1; + int i; + + // Get width in bytes. + width *= 2; + i = width / 8; + width -= i * 8; + + pxor_r2r( mm7, mm7 ); + while( i-- ) { + movd_m2r( *t1, mm0 ); + movd_m2r( *b1, mm1 ); + movd_m2r( *m0, mm2 ); + + movd_m2r( *(t1+4), mm3 ); + movd_m2r( *(b1+4), mm4 ); + movd_m2r( *(m0+4), mm5 ); + + punpcklbw_r2r( mm7, mm0 ); + punpcklbw_r2r( mm7, mm1 ); + punpcklbw_r2r( mm7, mm2 ); + + punpcklbw_r2r( mm7, mm3 ); + punpcklbw_r2r( mm7, mm4 ); + punpcklbw_r2r( mm7, mm5 ); + + psllw_i2r( 1, mm2 ); + psllw_i2r( 1, mm5 ); + paddw_r2r( mm0, mm2 ); + paddw_r2r( mm3, mm5 ); + paddw_r2r( mm1, mm2 ); + paddw_r2r( mm4, mm5 ); + psrlw_i2r( 2, mm2 ); + psrlw_i2r( 2, mm5 ); + packuswb_r2r( mm2, mm2 ); + packuswb_r2r( mm5, mm5 ); + + movd_r2m( mm2, *output ); + movd_r2m( mm5, *(output+4) ); + output += 8; + t1 += 8; + b1 += 8; + m0 += 8; + } + while( width-- ) { + *output++ = (*t1++ + *b1++ + (2 * *m0++))>>2; + } + sfence(); + emms(); +#endif +} + + +static deinterlace_method_t linearblendmethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "mplayer: Linear Blend", + "LinearBlend", + 2, + MM_ACCEL_X86_MMX, + 0, + 0, + 0, + 1, + deinterlace_scanline_linear_blend, + deinterlace_scanline_linear_blend2, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void linearblend_plugin_init( void ) +#endif +{ + register_deinterlace_method( &linearblendmethod ); +} + diff --git a/src/post/deinterlace/plugins/plugins.h b/src/post/deinterlace/plugins/plugins.h new file mode 100644 index 000000000..b39623bc1 --- /dev/null +++ b/src/post/deinterlace/plugins/plugins.h @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2002 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. + */ + +#ifndef TVTIME_PLUGINS_H_INCLUDED +#define TVTIME_PLUGINS_H_INCLUDED + +/** + * tvtime has a plugin system for deinterlacer plugins. + * However, at this point it's a bit silly to bother using + * them as 'dynamic' plugins. So, for the standard plugins, + * we allow them to be built into the executable, and their + * initializer methods go here. + */ + +void greedy_plugin_init( void ); +void greedy2frame_plugin_init( void ); +void twoframe_plugin_init( void ); +void linear_plugin_init( void ); +void weave_plugin_init( void ); +void videobob_plugin_init( void ); +void double_plugin_init( void ); +void linearblend_plugin_init( void ); +void scalerbob_plugin_init( void ); +void simplemo_plugin_init( void ); +void gamedither_plugin_init( void ); +void vfir_plugin_init( void ); + +void dscaler_greedy2frame_plugin_init( void ); +void dscaler_twoframe_plugin_init( void ); +void dscaler_greedyh_plugin_init( void ); +void dscaler_greedy_plugin_init( void ); +void dscaler_videobob_plugin_init( void ); +void dscaler_videoweave_plugin_init( void ); +void dscaler_oldgame_plugin_init( void ); +void dscaler_tomsmocomp_plugin_init( void ); + +#endif /* TVTIME_PLUGINS_H_INCLUDED */ 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 ); +} + diff --git a/src/post/deinterlace/plugins/weave.c b/src/post/deinterlace/plugins/weave.c new file mode 100644 index 000000000..3a9546aa8 --- /dev/null +++ b/src/post/deinterlace/plugins/weave.c @@ -0,0 +1,65 @@ +/** + * Pure weave deinterlacing plugin. + * + * Copyright (C) 2002 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> +#include "speedy.h" +#include "deinterlace.h" + +static void deinterlace_scanline_weave( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + 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 ); +} + + +static deinterlace_method_t weavemethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "Weave Last Field", + "Weave", + 2, + 0, + 0, + 0, + 0, + 1, + deinterlace_scanline_weave, + copy_scanline, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void weave_plugin_init( void ) +#endif +{ + register_deinterlace_method( &weavemethod ); +} + |