summaryrefslogtreecommitdiff
path: root/src/post/deinterlace/plugins
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-06-13 01:48:09 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-06-13 01:48:09 +0000
commitd349cabadd8f4b3530a9ae7049faa3f11387eab8 (patch)
tree8d6e84bc870bc7473ea55e18bf3b58062251c59d /src/post/deinterlace/plugins
parenta6b05cacbf52dd3b3b7aa4974d81e2221e203097 (diff)
downloadxine-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.am22
-rw-r--r--src/post/deinterlace/plugins/double.c65
-rw-r--r--src/post/deinterlace/plugins/greedy.c195
-rw-r--r--src/post/deinterlace/plugins/greedy2frame.c198
-rw-r--r--src/post/deinterlace/plugins/linear.c63
-rw-r--r--src/post/deinterlace/plugins/linearblend.c180
-rw-r--r--src/post/deinterlace/plugins/plugins.h52
-rw-r--r--src/post/deinterlace/plugins/vfir.c161
-rw-r--r--src/post/deinterlace/plugins/weave.c65
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 );
+}
+