From 43445935e82a7e9474092bf55b19d6c4d8fa1c7a Mon Sep 17 00:00:00 2001 From: Sebastian Dröge Date: Wed, 13 May 2009 10:46:40 +0200 Subject: Moved 'deinterlace2' from -bad to -good And rename it to deinterlace. --- configure.ac | 3 +- docs/plugins/Makefile.am | 1 + docs/plugins/gst-plugins-good-plugins-docs.sgml | 2 + docs/plugins/gst-plugins-good-plugins-sections.txt | 14 + docs/plugins/gst-plugins-good-plugins.args | 40 + docs/plugins/gst-plugins-good-plugins.hierarchy | 3 + docs/plugins/gst-plugins-good-plugins.interfaces | 2 + docs/plugins/inspect/plugin-deinterlace.xml | 34 + gst/deinterlace/Makefile.am | 48 + gst/deinterlace/gstdeinterlace.c | 1515 +++++++++++++++++++ gst/deinterlace/gstdeinterlace.h | 259 ++++ gst/deinterlace/tvtime/greedy.c | 488 +++++++ gst/deinterlace/tvtime/greedyh.asm | 250 ++++ gst/deinterlace/tvtime/greedyh.c | 420 ++++++ gst/deinterlace/tvtime/greedyhmacros.h | 75 + gst/deinterlace/tvtime/linear.c | 214 +++ gst/deinterlace/tvtime/linearblend.c | 231 +++ gst/deinterlace/tvtime/mmx.h | 723 ++++++++++ gst/deinterlace/tvtime/plugins.h | 54 + gst/deinterlace/tvtime/scalerbob.c | 74 + gst/deinterlace/tvtime/sse.h | 992 +++++++++++++ gst/deinterlace/tvtime/tomsmocomp.c | 211 +++ gst/deinterlace/tvtime/tomsmocomp/SearchLoop0A.inc | 15 + .../tvtime/tomsmocomp/SearchLoopBottom.inc | 174 +++ .../tvtime/tomsmocomp/SearchLoopEdgeA.inc | 11 + .../tvtime/tomsmocomp/SearchLoopEdgeA8.inc | 12 + .../tvtime/tomsmocomp/SearchLoopOddA.inc | 10 + .../tvtime/tomsmocomp/SearchLoopOddA2.inc | 5 + .../tvtime/tomsmocomp/SearchLoopOddA6.inc | 11 + .../tvtime/tomsmocomp/SearchLoopOddAH.inc | 10 + .../tvtime/tomsmocomp/SearchLoopOddAH2.inc | 5 + .../tvtime/tomsmocomp/SearchLoopTop.inc | 254 ++++ gst/deinterlace/tvtime/tomsmocomp/SearchLoopVA.inc | 6 + .../tvtime/tomsmocomp/SearchLoopVAH.inc | 6 + gst/deinterlace/tvtime/tomsmocomp/StrangeBob.inc | 435 ++++++ .../tvtime/tomsmocomp/TomsMoCompAll.inc | 241 ++++ .../tvtime/tomsmocomp/TomsMoCompAll2.inc | 243 ++++ gst/deinterlace/tvtime/tomsmocomp/WierdBob.inc | 286 ++++ .../tvtime/tomsmocomp/tomsmocompmacros.h | 164 +++ gst/deinterlace/tvtime/vfir.c | 187 +++ gst/deinterlace/tvtime/weave.c | 82 ++ gst/deinterlace/tvtime/weavebff.c | 88 ++ gst/deinterlace/tvtime/weavetff.c | 88 ++ gst/deinterlace/tvtime/x86-64_macros.inc | 82 ++ gst/deinterlace2/Makefile.am | 48 - gst/deinterlace2/gstdeinterlace2.c | 1517 -------------------- gst/deinterlace2/gstdeinterlace2.h | 259 ---- gst/deinterlace2/tvtime/greedy.c | 488 ------- gst/deinterlace2/tvtime/greedyh.asm | 250 ---- gst/deinterlace2/tvtime/greedyh.c | 420 ------ gst/deinterlace2/tvtime/greedyhmacros.h | 75 - gst/deinterlace2/tvtime/linear.c | 214 --- gst/deinterlace2/tvtime/linearblend.c | 231 --- gst/deinterlace2/tvtime/mmx.h | 723 ---------- gst/deinterlace2/tvtime/plugins.h | 54 - gst/deinterlace2/tvtime/scalerbob.c | 74 - gst/deinterlace2/tvtime/sse.h | 992 ------------- gst/deinterlace2/tvtime/tomsmocomp.c | 211 --- .../tvtime/tomsmocomp/SearchLoop0A.inc | 15 - .../tvtime/tomsmocomp/SearchLoopBottom.inc | 174 --- .../tvtime/tomsmocomp/SearchLoopEdgeA.inc | 11 - .../tvtime/tomsmocomp/SearchLoopEdgeA8.inc | 12 - .../tvtime/tomsmocomp/SearchLoopOddA.inc | 10 - .../tvtime/tomsmocomp/SearchLoopOddA2.inc | 5 - .../tvtime/tomsmocomp/SearchLoopOddA6.inc | 11 - .../tvtime/tomsmocomp/SearchLoopOddAH.inc | 10 - .../tvtime/tomsmocomp/SearchLoopOddAH2.inc | 5 - .../tvtime/tomsmocomp/SearchLoopTop.inc | 254 ---- .../tvtime/tomsmocomp/SearchLoopVA.inc | 6 - .../tvtime/tomsmocomp/SearchLoopVAH.inc | 6 - gst/deinterlace2/tvtime/tomsmocomp/StrangeBob.inc | 435 ------ .../tvtime/tomsmocomp/TomsMoCompAll.inc | 241 ---- .../tvtime/tomsmocomp/TomsMoCompAll2.inc | 243 ---- gst/deinterlace2/tvtime/tomsmocomp/WierdBob.inc | 286 ---- .../tvtime/tomsmocomp/tomsmocompmacros.h | 164 --- gst/deinterlace2/tvtime/vfir.c | 187 --- gst/deinterlace2/tvtime/weave.c | 82 -- gst/deinterlace2/tvtime/weavebff.c | 88 -- gst/deinterlace2/tvtime/weavetff.c | 88 -- gst/deinterlace2/tvtime/x86-64_macros.inc | 82 -- 80 files changed, 8067 insertions(+), 7972 deletions(-) create mode 100644 docs/plugins/inspect/plugin-deinterlace.xml create mode 100644 gst/deinterlace/Makefile.am create mode 100644 gst/deinterlace/gstdeinterlace.c create mode 100644 gst/deinterlace/gstdeinterlace.h create mode 100644 gst/deinterlace/tvtime/greedy.c create mode 100644 gst/deinterlace/tvtime/greedyh.asm create mode 100644 gst/deinterlace/tvtime/greedyh.c create mode 100644 gst/deinterlace/tvtime/greedyhmacros.h create mode 100644 gst/deinterlace/tvtime/linear.c create mode 100644 gst/deinterlace/tvtime/linearblend.c create mode 100644 gst/deinterlace/tvtime/mmx.h create mode 100644 gst/deinterlace/tvtime/plugins.h create mode 100644 gst/deinterlace/tvtime/scalerbob.c create mode 100644 gst/deinterlace/tvtime/sse.h create mode 100644 gst/deinterlace/tvtime/tomsmocomp.c create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoop0A.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopBottom.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA8.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA2.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA6.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH2.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopVA.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/SearchLoopVAH.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/StrangeBob.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll2.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/WierdBob.inc create mode 100644 gst/deinterlace/tvtime/tomsmocomp/tomsmocompmacros.h create mode 100644 gst/deinterlace/tvtime/vfir.c create mode 100644 gst/deinterlace/tvtime/weave.c create mode 100644 gst/deinterlace/tvtime/weavebff.c create mode 100644 gst/deinterlace/tvtime/weavetff.c create mode 100644 gst/deinterlace/tvtime/x86-64_macros.inc delete mode 100644 gst/deinterlace2/Makefile.am delete mode 100644 gst/deinterlace2/gstdeinterlace2.c delete mode 100644 gst/deinterlace2/gstdeinterlace2.h delete mode 100644 gst/deinterlace2/tvtime/greedy.c delete mode 100644 gst/deinterlace2/tvtime/greedyh.asm delete mode 100644 gst/deinterlace2/tvtime/greedyh.c delete mode 100644 gst/deinterlace2/tvtime/greedyhmacros.h delete mode 100644 gst/deinterlace2/tvtime/linear.c delete mode 100644 gst/deinterlace2/tvtime/linearblend.c delete mode 100644 gst/deinterlace2/tvtime/mmx.h delete mode 100644 gst/deinterlace2/tvtime/plugins.h delete mode 100644 gst/deinterlace2/tvtime/scalerbob.c delete mode 100644 gst/deinterlace2/tvtime/sse.h delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp.c delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoop0A.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopBottom.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA8.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA2.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA6.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH2.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopTop.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVA.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVAH.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/StrangeBob.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll2.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/WierdBob.inc delete mode 100644 gst/deinterlace2/tvtime/tomsmocomp/tomsmocompmacros.h delete mode 100644 gst/deinterlace2/tvtime/vfir.c delete mode 100644 gst/deinterlace2/tvtime/weave.c delete mode 100644 gst/deinterlace2/tvtime/weavebff.c delete mode 100644 gst/deinterlace2/tvtime/weavetff.c delete mode 100644 gst/deinterlace2/tvtime/x86-64_macros.inc diff --git a/configure.ac b/configure.ac index 0ee24c81..01e55d2a 100644 --- a/configure.ac +++ b/configure.ac @@ -280,6 +280,7 @@ AG_GST_CHECK_PLUGIN(autodetect) AG_GST_CHECK_PLUGIN(avi) AG_GST_CHECK_PLUGIN(cutter) AG_GST_CHECK_PLUGIN(debugutils) +AG_GST_CHECK_PLUGIN(deinterlace) AG_GST_CHECK_PLUGIN(effectv) AG_GST_CHECK_PLUGIN(equalizer) AG_GST_CHECK_PLUGIN(flv) @@ -1055,7 +1056,7 @@ gst/auparse/Makefile gst/autodetect/Makefile gst/avi/Makefile gst/cutter/Makefile -gst/debugutils/Makefile +gst/deinterlace/Makefile gst/effectv/Makefile gst/equalizer/Makefile gst/flv/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 7e05a8ec..790a4e17 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -137,6 +137,7 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/cutter/gstcutter.h \ $(top_srcdir)/gst/debugutils/gsttaginject.h \ $(top_srcdir)/gst/debugutils/progressreport.h \ + $(top_srcdir)/gst/deinterlace/gstdeinterlace.h \ $(top_srcdir)/gst/equalizer/gstiirequalizer.h \ $(top_srcdir)/gst/equalizer/gstiirequalizer3bands.h \ $(top_srcdir)/gst/equalizer/gstiirequalizer10bands.h \ diff --git a/docs/plugins/gst-plugins-good-plugins-docs.sgml b/docs/plugins/gst-plugins-good-plugins-docs.sgml index 105bc5b8..2e61ed82 100644 --- a/docs/plugins/gst-plugins-good-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-good-plugins-docs.sgml @@ -50,6 +50,7 @@ + @@ -155,6 +156,7 @@ + diff --git a/docs/plugins/gst-plugins-good-plugins-sections.txt b/docs/plugins/gst-plugins-good-plugins-sections.txt index ad7a528f..62c24bf4 100644 --- a/docs/plugins/gst-plugins-good-plugins-sections.txt +++ b/docs/plugins/gst-plugins-good-plugins-sections.txt @@ -464,6 +464,20 @@ GstCutterClass gst_cutter_get_type +
+element-deinterlace +deinterlace +GstDeinterlace + +GstDeinterlaceClass +GST_IS_DEINTERLACE +GST_IS_DEINTERLACE_CLASS +GST_DEINTERLACE +GST_DEINTERLACE_CLASS +GST_TYPE_DEINTERLACE +gst_deinterlace_get_type +
+
element-deinterleave deinterleave diff --git a/docs/plugins/gst-plugins-good-plugins.args b/docs/plugins/gst-plugins-good-plugins.args index 685d7c26..dfa694c4 100644 --- a/docs/plugins/gst-plugins-good-plugins.args +++ b/docs/plugins/gst-plugins-good-plugins.args @@ -19918,3 +19918,43 @@ TRUE + +GstDeinterlace::fields +GstDeinterlaceFields + +rw +fields +Fields to use for deinterlacing. +All fields + + + +GstDeinterlace::method +GstDeinterlaceMethods + +rw +Method +Deinterlace Method. +Motion Adaptive: Advanced Detection + + + +GstDeinterlace::mode +GstDeinterlaceModes + +rw +Mode +Deinterlace Mode. +Enfore deinterlacing + + + +GstDeinterlace::tff +GstDeinterlaceFieldLayout + +rw +tff +Deinterlace top field first. +Auto detection + + diff --git a/docs/plugins/gst-plugins-good-plugins.hierarchy b/docs/plugins/gst-plugins-good-plugins.hierarchy index 01abd2d6..4534a398 100644 --- a/docs/plugins/gst-plugins-good-plugins.hierarchy +++ b/docs/plugins/gst-plugins-good-plugins.hierarchy @@ -142,6 +142,8 @@ GObject GstID3Demux GstGoom GstGoom2k1 + GstFLVDemux + GstFlvMux GstMultipartDemux GstMultipartMux GstMuLawEnc @@ -187,6 +189,7 @@ GObject GstInterleave GstDeinterleave GstMonoscope + GstDeinterlace GstWavEnc GstAuParse GstRTPDepay diff --git a/docs/plugins/gst-plugins-good-plugins.interfaces b/docs/plugins/gst-plugins-good-plugins.interfaces index d5984d54..d1b0392e 100644 --- a/docs/plugins/gst-plugins-good-plugins.interfaces +++ b/docs/plugins/gst-plugins-good-plugins.interfaces @@ -40,4 +40,6 @@ GstSpeexEnc GstTagSetter GstPreset GstOssMixerElement GstImplementsInterface GstMixer GstMatroskaMux GstTagSetter GstVideoMixer GstChildProxy +GstFlvMux GstTagSetter GstAviMux GstTagSetter +GstDeinterlace GstChildProxy diff --git a/docs/plugins/inspect/plugin-deinterlace.xml b/docs/plugins/inspect/plugin-deinterlace.xml new file mode 100644 index 00000000..ade0bb3f --- /dev/null +++ b/docs/plugins/inspect/plugin-deinterlace.xml @@ -0,0 +1,34 @@ + + deinterlace + Deinterlacer + ../../gst/deinterlace/.libs/libgstdeinterlace.so + libgstdeinterlace.so + 0.10.14.2 + LGPL + gst-plugins-good + GStreamer Good Plug-ins CVS/prerelease + Unknown package origin + + + deinterlace + Deinterlacer + Filter/Video + Deinterlace Methods ported from DScaler/TvTime + Martin Eikermann <meiker@upb.de>, Sebastian Dröge <slomo@circular-chaos.org> + + + sink + sink + always +
video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst/deinterlace/Makefile.am b/gst/deinterlace/Makefile.am new file mode 100644 index 00000000..216fdbeb --- /dev/null +++ b/gst/deinterlace/Makefile.am @@ -0,0 +1,48 @@ +plugin_LTLIBRARIES = libgstdeinterlace.la + +libgstdeinterlace_la_SOURCES = \ + gstdeinterlace.c \ + tvtime/greedy.c \ + tvtime/greedyh.c \ + tvtime/vfir.c \ + tvtime/tomsmocomp.c \ + tvtime/weavetff.c \ + tvtime/weavebff.c \ + tvtime/weave.c \ + tvtime/linear.c \ + tvtime/linearblend.c \ + tvtime/scalerbob.c + +libgstdeinterlace_la_CFLAGS = $(GST_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(LIBOIL_CFLAGS) +libgstdeinterlace_la_LIBADD = $(GST_LIBS) \ + $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(LIBOIL_LIBS) +libgstdeinterlace_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstdeinterlace_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstdeinterlace.h \ + tvtime/mmx.h \ + tvtime/sse.h \ + tvtime/greedyh.asm \ + tvtime/greedyhmacros.h \ + tvtime/plugins.h \ + tvtime/x86-64_macros.inc \ + tvtime/tomsmocomp/SearchLoop0A.inc \ + tvtime/tomsmocomp/SearchLoopBottom.inc \ + tvtime/tomsmocomp/SearchLoopEdgeA8.inc \ + tvtime/tomsmocomp/SearchLoopEdgeA.inc \ + tvtime/tomsmocomp/SearchLoopOddA2.inc \ + tvtime/tomsmocomp/SearchLoopOddA6.inc \ + tvtime/tomsmocomp/SearchLoopOddAH2.inc \ + tvtime/tomsmocomp/SearchLoopOddAH.inc \ + tvtime/tomsmocomp/SearchLoopOddA.inc \ + tvtime/tomsmocomp/SearchLoopTop.inc \ + tvtime/tomsmocomp/SearchLoopVAH.inc \ + tvtime/tomsmocomp/SearchLoopVA.inc \ + tvtime/tomsmocomp/StrangeBob.inc \ + tvtime/tomsmocomp/TomsMoCompAll2.inc \ + tvtime/tomsmocomp/TomsMoCompAll.inc \ + tvtime/tomsmocomp/tomsmocompmacros.h \ + tvtime/tomsmocomp/WierdBob.inc + diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c new file mode 100644 index 00000000..af730f4f --- /dev/null +++ b/gst/deinterlace/gstdeinterlace.c @@ -0,0 +1,1515 @@ +/* + * GStreamer + * Copyright (C) 2005 Martin Eikermann + * Copyright (C) 2008-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-deinterlace + * + * deinterlace deinterlaces interlaced video frames to progressive video frames. + * For this different algorithms can be selected which will be described later. + * + * + * Example launch line + * |[ + * gst-launch -v filesrc location=/path/to/file ! decodebin2 ! ffmpegcolorspace ! deinterlace ! ffmpegcolorspace ! autovideosink + * ]| This pipeline deinterlaces a video file with the default deinterlacing options. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gstdeinterlace.h" +#include "tvtime/plugins.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (deinterlace_debug); +#define GST_CAT_DEFAULT (deinterlace_debug) + +/* Object signals and args */ +enum +{ + LAST_SIGNAL +}; + +/* Properties */ + +#define DEFAULT_MODE GST_DEINTERLACE_MODE_INTERLACED +#define DEFAULT_METHOD GST_DEINTERLACE_GREEDY_H +#define DEFAULT_FIELDS GST_DEINTERLACE_ALL +#define DEFAULT_FIELD_LAYOUT GST_DEINTERLACE_LAYOUT_AUTO + +enum +{ + PROP_0, + PROP_MODE, + PROP_METHOD, + PROP_FIELDS, + PROP_FIELD_LAYOUT, + PROP_LAST +}; + +G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT); + +static void +gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass) +{ + +} + +static void +gst_deinterlace_method_init (GstDeinterlaceMethod * self) +{ + +} + +static void +gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self, + GstDeinterlace * parent, GstBuffer * outbuf) +{ + GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self); + + klass->deinterlace_frame (self, parent, outbuf); +} + +static gint +gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self) +{ + GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self); + + return klass->fields_required; +} + +static gint +gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self) +{ + GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self); + + return klass->latency; +} + + +G_DEFINE_TYPE (GstDeinterlaceSimpleMethod, gst_deinterlace_simple_method, + GST_TYPE_DEINTERLACE_METHOD); + +static void +gst_deinterlace_simple_method_interpolate_scanline (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->m1, parent->row_stride); +} + +static void +gst_deinterlace_simple_method_copy_scanline (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->m0, parent->row_stride); +} + +static void +gst_deinterlace_simple_method_deinterlace_frame (GstDeinterlaceMethod * self, + GstDeinterlace * parent, GstBuffer * outbuf) +{ + GstDeinterlaceSimpleMethodClass *dsm_class = + GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self); + GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); + GstDeinterlaceScanlineData scanlines; + guint8 *out = GST_BUFFER_DATA (outbuf); + guint8 *field0 = NULL, *field1 = NULL, *field2 = NULL, *field3 = NULL; + gint cur_field_idx = parent->history_count - dm_class->fields_required; + guint cur_field_flags = parent->field_history[cur_field_idx].flags; + gint line; + + field0 = GST_BUFFER_DATA (parent->field_history[cur_field_idx].buf); + + g_assert (dm_class->fields_required <= 4); + + if (dm_class->fields_required >= 2) + field1 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 1].buf); + if (dm_class->fields_required >= 3) + field2 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 2].buf); + if (dm_class->fields_required >= 4) + field3 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 3].buf); + + + if (cur_field_flags == PICTURE_INTERLACED_BOTTOM) { + /* double the first scanline of the bottom field */ + oil_memcpy (out, field0, parent->row_stride); + out += parent->row_stride; + } + + oil_memcpy (out, field0, parent->row_stride); + out += parent->row_stride; + + for (line = 2; line <= parent->field_height; line++) { + + memset (&scanlines, 0, sizeof (scanlines)); + scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM); + + /* interp. scanline */ + scanlines.t0 = field0; + scanlines.b0 = field0 + parent->field_stride; + + if (field1 != NULL) { + scanlines.tt1 = field1; + scanlines.m1 = field1 + parent->field_stride; + scanlines.bb1 = field1 + parent->field_stride * 2; + field1 += parent->field_stride; + } + + if (field2 != NULL) { + scanlines.t2 = field2; + scanlines.b2 = field2 + parent->field_stride; + } + + if (field3 != NULL) { + scanlines.tt3 = field3; + scanlines.m3 = field3 + parent->field_stride; + scanlines.bb3 = field3 + parent->field_stride * 2; + field3 += parent->field_stride; + } + + /* set valid data for corner cases */ + if (line == 2) { + scanlines.tt1 = scanlines.bb1; + scanlines.tt3 = scanlines.bb3; + } else if (line == parent->field_height) { + scanlines.bb1 = scanlines.tt1; + scanlines.bb3 = scanlines.tt3; + } + + dsm_class->interpolate_scanline (self, parent, out, &scanlines, + parent->frame_width); + out += parent->row_stride; + + memset (&scanlines, 0, sizeof (scanlines)); + scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM); + + /* copy a scanline */ + scanlines.tt0 = field0; + scanlines.m0 = field0 + parent->field_stride; + scanlines.bb0 = field0 + parent->field_stride * 2; + field0 += parent->field_stride; + + if (field1 != NULL) { + scanlines.t1 = field1; + scanlines.b1 = field1 + parent->field_stride; + } + + if (field2 != NULL) { + scanlines.tt2 = field2; + scanlines.m2 = field2 + parent->field_stride; + scanlines.bb2 = field2 + parent->field_stride * 2; + field2 += parent->field_stride; + } + + if (field3 != NULL) { + scanlines.t3 = field3; + scanlines.b3 = field3 + parent->field_stride; + } + + /* set valid data for corner cases */ + if (line == parent->field_height) { + scanlines.bb0 = scanlines.tt0; + scanlines.b1 = scanlines.t1; + scanlines.bb2 = scanlines.tt2; + scanlines.b3 = scanlines.t3; + } + + dsm_class->copy_scanline (self, parent, out, &scanlines, + parent->frame_width); + out += parent->row_stride; + } + + if (cur_field_flags == PICTURE_INTERLACED_TOP) { + /* double the last scanline of the top field */ + oil_memcpy (out, field0, parent->row_stride); + } +} + +static void +gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass * + klass) +{ + GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass; + + dm_class->deinterlace_frame = gst_deinterlace_simple_method_deinterlace_frame; + dm_class->fields_required = 2; + + klass->interpolate_scanline = + gst_deinterlace_simple_method_interpolate_scanline; + klass->copy_scanline = gst_deinterlace_simple_method_copy_scanline; +} + +static void +gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self) +{ +} + +#define GST_TYPE_DEINTERLACE_METHODS (gst_deinterlace_methods_get_type ()) +static GType +gst_deinterlace_methods_get_type (void) +{ + static GType deinterlace_methods_type = 0; + + static const GEnumValue methods_types[] = { + {GST_DEINTERLACE_TOMSMOCOMP, "Motion Adaptive: Motion Search", + "tomsmocomp"}, + {GST_DEINTERLACE_GREEDY_H, "Motion Adaptive: Advanced Detection", + "greedyh"}, + {GST_DEINTERLACE_GREEDY_L, "Motion Adaptive: Simple Detection", "greedyl"}, + {GST_DEINTERLACE_VFIR, "Blur Vertical", "vfir"}, + {GST_DEINTERLACE_LINEAR, "Television: Full resolution", "linear"}, + {GST_DEINTERLACE_LINEAR_BLEND, "Blur: Temporal", "linearblend"}, + {GST_DEINTERLACE_SCALER_BOB, "Double lines", "scalerbob"}, + {GST_DEINTERLACE_WEAVE, "Weave", "weave"}, + {GST_DEINTERLACE_WEAVE_TFF, "Progressive: Top Field First", "weavetff"}, + {GST_DEINTERLACE_WEAVE_BFF, "Progressive: Bottom Field First", "weavebff"}, + {0, NULL, NULL}, + }; + + if (!deinterlace_methods_type) { + deinterlace_methods_type = + g_enum_register_static ("GstDeinterlaceMethods", methods_types); + } + return deinterlace_methods_type; +} + +#define GST_TYPE_DEINTERLACE_FIELDS (gst_deinterlace_fields_get_type ()) +static GType +gst_deinterlace_fields_get_type (void) +{ + static GType deinterlace_fields_type = 0; + + static const GEnumValue fields_types[] = { + {GST_DEINTERLACE_ALL, "All fields", "all"}, + {GST_DEINTERLACE_TF, "Top fields only", "top"}, + {GST_DEINTERLACE_BF, "Bottom fields only", "bottom"}, + {0, NULL, NULL}, + }; + + if (!deinterlace_fields_type) { + deinterlace_fields_type = + g_enum_register_static ("GstDeinterlaceFields", fields_types); + } + return deinterlace_fields_type; +} + +#define GST_TYPE_DEINTERLACE_FIELD_LAYOUT (gst_deinterlace_field_layout_get_type ()) +static GType +gst_deinterlace_field_layout_get_type (void) +{ + static GType deinterlace_field_layout_type = 0; + + static const GEnumValue field_layout_types[] = { + {GST_DEINTERLACE_LAYOUT_AUTO, "Auto detection", "auto"}, + {GST_DEINTERLACE_LAYOUT_TFF, "Top field first", "tff"}, + {GST_DEINTERLACE_LAYOUT_BFF, "Bottom field first", "bff"}, + {0, NULL, NULL}, + }; + + if (!deinterlace_field_layout_type) { + deinterlace_field_layout_type = + g_enum_register_static ("GstDeinterlaceFieldLayout", + field_layout_types); + } + return deinterlace_field_layout_type; +} + +#define GST_TYPE_DEINTERLACE_MODES (gst_deinterlace_modes_get_type ()) +static GType +gst_deinterlace_modes_get_type (void) +{ + static GType deinterlace_modes_type = 0; + + static const GEnumValue modes_types[] = { + {GST_DEINTERLACE_MODE_AUTO, "Auto detection", "auto"}, + {GST_DEINTERLACE_MODE_INTERLACED, "Enfore deinterlacing", "interlaced"}, + {GST_DEINTERLACE_MODE_DISABLED, "Run in passthrough mode", "disabled"}, + {0, NULL, NULL}, + }; + + if (!deinterlace_modes_type) { + deinterlace_modes_type = + g_enum_register_static ("GstDeinterlaceModes", modes_types); + } + return deinterlace_modes_type; +} + +static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2") ";" + GST_VIDEO_CAPS_YUV ("YVYU")) + ); + +static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2") ";" + GST_VIDEO_CAPS_YUV ("YVYU")) + ); + +static void gst_deinterlace_finalize (GObject * self); +static void gst_deinterlace_set_property (GObject * self, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_deinterlace_get_property (GObject * self, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstCaps *gst_deinterlace_getcaps (GstPad * pad); +static gboolean gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_deinterlace_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_deinterlace_chain (GstPad * pad, GstBuffer * buffer); +static GstStateChangeReturn gst_deinterlace_change_state (GstElement * element, + GstStateChange transition); + +static gboolean gst_deinterlace_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_deinterlace_src_query (GstPad * pad, GstQuery * query); +static const GstQueryType *gst_deinterlace_src_query_types (GstPad * pad); + +static void gst_deinterlace_reset (GstDeinterlace * self); + +static void gst_deinterlace_child_proxy_interface_init (gpointer g_iface, + gpointer iface_data); + +static void +_do_init (GType object_type) +{ + const GInterfaceInfo child_proxy_interface_info = { + (GInterfaceInitFunc) gst_deinterlace_child_proxy_interface_init, + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY, + &child_proxy_interface_info); +} + +GST_BOILERPLATE_FULL (GstDeinterlace, gst_deinterlace, GstElement, + GST_TYPE_ELEMENT, _do_init); + +static void +gst_deinterlace_set_method (GstDeinterlace * self, GstDeinterlaceMethods method) +{ + + if (self->method) { + gst_child_proxy_child_removed (GST_OBJECT (self), + GST_OBJECT (self->method)); + gst_object_unparent (GST_OBJECT (self->method)); + self->method = NULL; + } + + switch (method) { + case GST_DEINTERLACE_TOMSMOCOMP: + self->method = g_object_new (GST_TYPE_DEINTERLACE_TOMSMOCOMP, NULL); + break; + case GST_DEINTERLACE_GREEDY_H: + self->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_H, NULL); + break; + case GST_DEINTERLACE_GREEDY_L: + self->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_L, NULL); + break; + case GST_DEINTERLACE_VFIR: + self->method = g_object_new (GST_TYPE_DEINTERLACE_VFIR, NULL); + break; + case GST_DEINTERLACE_LINEAR: + self->method = g_object_new (GST_TYPE_DEINTERLACE_LINEAR, NULL); + break; + case GST_DEINTERLACE_LINEAR_BLEND: + self->method = g_object_new (GST_TYPE_DEINTERLACE_LINEAR_BLEND, NULL); + break; + case GST_DEINTERLACE_SCALER_BOB: + self->method = g_object_new (GST_TYPE_DEINTERLACE_SCALER_BOB, NULL); + break; + case GST_DEINTERLACE_WEAVE: + self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE, NULL); + break; + case GST_DEINTERLACE_WEAVE_TFF: + self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE_TFF, NULL); + break; + case GST_DEINTERLACE_WEAVE_BFF: + self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE_BFF, NULL); + break; + default: + GST_WARNING_OBJECT (self, "Invalid Deinterlacer Method"); + return; + } + + self->method_id = method; + + gst_object_set_name (GST_OBJECT (self->method), "method"); + gst_object_set_parent (GST_OBJECT (self->method), GST_OBJECT (self)); + gst_child_proxy_child_added (GST_OBJECT (self), GST_OBJECT (self->method)); +} + +static void +gst_deinterlace_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_templ)); + + gst_element_class_set_details_simple (element_class, + "Deinterlacer", + "Filter/Video", + "Deinterlace Methods ported from DScaler/TvTime", + "Martin Eikermann , " + "Sebastian Dröge "); +} + +static void +gst_deinterlace_class_init (GstDeinterlaceClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + GstElementClass *element_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_deinterlace_set_property; + gobject_class->get_property = gst_deinterlace_get_property; + gobject_class->finalize = gst_deinterlace_finalize; + + /** + * GstDeinterlace:mode + * + * This selects whether the deinterlacing methods should + * always be applied or if they should only be applied + * on content that has the "interlaced" flag on the caps. + * + */ + g_object_class_install_property (gobject_class, PROP_MODE, + g_param_spec_enum ("mode", + "Mode", + "Deinterlace Mode", + GST_TYPE_DEINTERLACE_MODES, + DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + /** + * GstDeinterlace:method + * + * Selects the different deinterlacing algorithms that can be used. + * These provide different quality and CPU usage. + * + * Some methods provide parameters which can be set by getting + * the "method" child via the #GstChildProxy interface and + * setting the appropiate properties on it. + * + * + * + * + * tomsmocomp + * Motion Adaptive: Motion Search + * + * + * + * + * greedyh + * Motion Adaptive: Advanced Detection + * + * + * + * + * greedyl + * Motion Adaptive: Simple Detection + * + * + * + * + * vfir + * Blur vertical + * + * + * + * + * linear + * Linear interpolation + * + * + * + * + * linearblend + * Linear interpolation in time domain + * + * + * + * + * scalerbob + * Double lines + * + * + * + * + * weave + * Weave + * + * + * + * + * weavetff + * Progressive: Top Field First + * + * + * + * + * weavebff + * Progressive: Bottom Field First + * + * + * + */ + g_object_class_install_property (gobject_class, PROP_METHOD, + g_param_spec_enum ("method", + "Method", + "Deinterlace Method", + GST_TYPE_DEINTERLACE_METHODS, + DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + /** + * GstDeinterlace:fields + * + * This selects which fields should be output. If "all" is selected + * the output framerate will be double. + * + */ + g_object_class_install_property (gobject_class, PROP_FIELDS, + g_param_spec_enum ("fields", + "fields", + "Fields to use for deinterlacing", + GST_TYPE_DEINTERLACE_FIELDS, + DEFAULT_FIELDS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + /** + * GstDeinterlace:layout + * + * This selects which fields is the first in time. + * + */ + g_object_class_install_property (gobject_class, PROP_FIELD_LAYOUT, + g_param_spec_enum ("tff", + "tff", + "Deinterlace top field first", + GST_TYPE_DEINTERLACE_FIELD_LAYOUT, + DEFAULT_FIELD_LAYOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_deinterlace_change_state); +} + +static GstObject * +gst_deinterlace_child_proxy_get_child_by_index (GstChildProxy * child_proxy, + guint index) +{ + GstDeinterlace *self = GST_DEINTERLACE (child_proxy); + + g_return_val_if_fail (index == 0, NULL); + + return gst_object_ref (self->method); +} + +static guint +gst_deinterlace_child_proxy_get_children_count (GstChildProxy * child_proxy) +{ + return 1; +} + +static void +gst_deinterlace_child_proxy_interface_init (gpointer g_iface, + gpointer iface_data) +{ + GstChildProxyInterface *iface = g_iface; + + iface->get_child_by_index = gst_deinterlace_child_proxy_get_child_by_index; + iface->get_children_count = gst_deinterlace_child_proxy_get_children_count; +} + +static void +gst_deinterlace_init (GstDeinterlace * self, GstDeinterlaceClass * klass) +{ + self->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); + gst_pad_set_chain_function (self->sinkpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_chain)); + gst_pad_set_event_function (self->sinkpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_sink_event)); + gst_pad_set_setcaps_function (self->sinkpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_setcaps)); + gst_pad_set_getcaps_function (self->sinkpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_getcaps)); + gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); + + self->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); + gst_pad_set_event_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_src_event)); + gst_pad_set_query_type_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_src_query_types)); + gst_pad_set_query_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_src_query)); + gst_pad_set_setcaps_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_setcaps)); + gst_pad_set_getcaps_function (self->srcpad, + GST_DEBUG_FUNCPTR (gst_deinterlace_getcaps)); + gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + + gst_element_no_more_pads (GST_ELEMENT (self)); + + self->mode = DEFAULT_MODE; + gst_deinterlace_set_method (self, DEFAULT_METHOD); + self->fields = DEFAULT_FIELDS; + self->field_layout = DEFAULT_FIELD_LAYOUT; + + gst_deinterlace_reset (self); +} + +static void +gst_deinterlace_reset_history (GstDeinterlace * self) +{ + gint i; + + for (i = 0; i < self->history_count; i++) { + if (self->field_history[i].buf) { + gst_buffer_unref (self->field_history[i].buf); + self->field_history[i].buf = NULL; + } + } + memset (self->field_history, 0, MAX_FIELD_HISTORY * sizeof (GstPicture)); + self->history_count = 0; +} + +static void +gst_deinterlace_reset (GstDeinterlace * self) +{ + self->row_stride = 0; + self->frame_width = 0; + self->frame_height = 0; + self->frame_rate_n = 0; + self->frame_rate_d = 0; + self->field_height = 0; + self->field_stride = 0; + + gst_deinterlace_reset_history (self); +} + +static void +gst_deinterlace_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeinterlace *self; + + g_return_if_fail (GST_IS_DEINTERLACE (object)); + self = GST_DEINTERLACE (object); + + switch (prop_id) { + case PROP_MODE:{ + gint oldmode; + + GST_OBJECT_LOCK (self); + oldmode = self->mode; + self->mode = g_value_get_enum (value); + if (self->mode != oldmode && GST_PAD_CAPS (self->srcpad)) + gst_deinterlace_setcaps (self->sinkpad, GST_PAD_CAPS (self->sinkpad)); + GST_OBJECT_UNLOCK (self); + break; + } + case PROP_METHOD: + gst_deinterlace_set_method (self, g_value_get_enum (value)); + break; + case PROP_FIELDS:{ + gint oldfields; + + GST_OBJECT_LOCK (self); + oldfields = self->fields; + self->fields = g_value_get_enum (value); + if (self->fields != oldfields && GST_PAD_CAPS (self->srcpad)) + gst_deinterlace_setcaps (self->sinkpad, GST_PAD_CAPS (self->sinkpad)); + GST_OBJECT_UNLOCK (self); + break; + } + case PROP_FIELD_LAYOUT: + self->field_layout = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); + } + +} + +static void +gst_deinterlace_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeinterlace *self; + + g_return_if_fail (GST_IS_DEINTERLACE (object)); + self = GST_DEINTERLACE (object); + + switch (prop_id) { + case PROP_MODE: + g_value_set_enum (value, self->mode); + break; + case PROP_METHOD: + g_value_set_enum (value, self->method_id); + break; + case PROP_FIELDS: + g_value_set_enum (value, self->fields); + break; + case PROP_FIELD_LAYOUT: + g_value_set_enum (value, self->field_layout); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); + } +} + +static void +gst_deinterlace_finalize (GObject * object) +{ + GstDeinterlace *self = GST_DEINTERLACE (object); + + gst_deinterlace_reset (self); + + if (self->method) { + gst_object_unparent (GST_OBJECT (self->method)); + self->method = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstBuffer * +gst_deinterlace_pop_history (GstDeinterlace * self) +{ + GstBuffer *buffer = NULL; + + g_assert (self->history_count > 0); + + buffer = self->field_history[self->history_count - 1].buf; + + self->history_count--; + GST_DEBUG_OBJECT (self, "pop, size(history): %d", self->history_count); + + return buffer; +} + +#if 0 +static GstBuffer * +gst_deinterlace_head_history (GstDeinterlace * self) +{ + return self->field_history[self->history_count - 1].buf; +} +#endif + + +/* invariant: field with smallest timestamp is self->field_history[self->history_count-1] + +*/ + +static void +gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer) +{ + int i = 1; + GstClockTime timestamp; + GstDeinterlaceFieldLayout field_layout = self->field_layout; + gboolean repeated = GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_RFF); + gboolean tff = GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_TFF); + gboolean onefield = + GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_ONEFIELD); + GstBuffer *field1, *field2; + guint fields_to_push = (onefield) ? 1 : (!repeated) ? 2 : 3; + gint field1_flags, field2_flags; + + g_assert (self->history_count < MAX_FIELD_HISTORY - fields_to_push); + + for (i = MAX_FIELD_HISTORY - 1; i >= fields_to_push; i--) { + self->field_history[i].buf = self->field_history[i - fields_to_push].buf; + self->field_history[i].flags = + self->field_history[i - fields_to_push].flags; + } + + if (field_layout == GST_DEINTERLACE_LAYOUT_AUTO) { + if (!self->interlaced) { + GST_WARNING_OBJECT (self, "Can't detect field layout -- assuming TFF"); + field_layout = GST_DEINTERLACE_LAYOUT_TFF; + } else if (tff) { + field_layout = GST_DEINTERLACE_LAYOUT_TFF; + } else { + field_layout = GST_DEINTERLACE_LAYOUT_BFF; + } + } + + if (field_layout == GST_DEINTERLACE_LAYOUT_TFF) { + GST_DEBUG_OBJECT (self, "Top field first"); + field1 = gst_buffer_ref (buffer); + field1_flags = PICTURE_INTERLACED_TOP; + field2 = gst_buffer_create_sub (buffer, self->row_stride, + GST_BUFFER_SIZE (buffer) - self->row_stride); + field2_flags = PICTURE_INTERLACED_BOTTOM; + } else { + GST_DEBUG_OBJECT (self, "Bottom field first"); + field1 = gst_buffer_create_sub (buffer, self->row_stride, + GST_BUFFER_SIZE (buffer) - self->row_stride); + field1_flags = PICTURE_INTERLACED_BOTTOM; + field2 = gst_buffer_ref (buffer); + field2_flags = PICTURE_INTERLACED_TOP; + } + + /* Timestamps are assigned to the field buffers under the assumption that + the timestamp of the buffer equals the first fields timestamp */ + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_TIMESTAMP (field1) = timestamp; + GST_BUFFER_TIMESTAMP (field2) = timestamp + self->field_duration; + if (repeated) + GST_BUFFER_TIMESTAMP (field2) += self->field_duration; + + if (repeated) { + self->field_history[0].buf = field2; + self->field_history[0].flags = field2_flags; + self->field_history[1].buf = gst_buffer_ref (field1); + GST_BUFFER_TIMESTAMP (self->field_history[1].buf) += self->field_duration; + self->field_history[1].flags = field1_flags; + self->field_history[2].buf = field1; + self->field_history[2].flags = field1_flags; + } else if (!onefield) { + self->field_history[0].buf = field2; + self->field_history[0].flags = field2_flags; + self->field_history[1].buf = field1; + self->field_history[1].flags = field1_flags; + } else { /* onefield */ + self->field_history[0].buf = field1; + self->field_history[0].flags = field1_flags; + gst_buffer_unref (field2); + } + + self->history_count += fields_to_push; + GST_DEBUG_OBJECT (self, "push, size(history): %d", self->history_count); + + gst_buffer_unref (buffer); +} + +static GstFlowReturn +gst_deinterlace_chain (GstPad * pad, GstBuffer * buf) +{ + GstDeinterlace *self = NULL; + GstClockTime timestamp; + GstFlowReturn ret = GST_FLOW_OK; + gint fields_required = 0; + gint cur_field_idx = 0; + GstBuffer *outbuf; + + self = GST_DEINTERLACE (GST_PAD_PARENT (pad)); + + if (self->mode == GST_DEINTERLACE_MODE_DISABLED || (!self->interlaced + && self->mode != GST_DEINTERLACE_MODE_INTERLACED)) + return gst_pad_push (self->srcpad, buf); + + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { + GST_DEBUG_OBJECT (self, "DISCONT buffer, resetting history"); + gst_deinterlace_reset_history (self); + } + + gst_deinterlace_push_history (self, buf); + buf = NULL; + + fields_required = gst_deinterlace_method_get_fields_required (self->method); + + /* Not enough fields in the history */ + if (self->history_count < fields_required + 1) { + /* TODO: do bob or just forward frame */ + GST_DEBUG_OBJECT (self, "HistoryCount=%d", self->history_count); + return GST_FLOW_OK; + } + + while (self->history_count >= fields_required) { + if (self->fields == GST_DEINTERLACE_ALL) + GST_DEBUG_OBJECT (self, "All fields"); + if (self->fields == GST_DEINTERLACE_TF) + GST_DEBUG_OBJECT (self, "Top fields"); + if (self->fields == GST_DEINTERLACE_BF) + GST_DEBUG_OBJECT (self, "Bottom fields"); + + cur_field_idx = self->history_count - fields_required; + + if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP + && self->fields == GST_DEINTERLACE_TF) || + self->fields == GST_DEINTERLACE_ALL) { + GST_DEBUG_OBJECT (self, "deinterlacing top field"); + + /* create new buffer */ + ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad, + GST_BUFFER_OFFSET_NONE, self->frame_size, + GST_PAD_CAPS (self->srcpad), &outbuf); + if (ret != GST_FLOW_OK) + return ret; + + /* do magic calculus */ + gst_deinterlace_method_deinterlace_frame (self->method, self, outbuf); + + g_assert (self->history_count - 1 - + gst_deinterlace_method_get_latency (self->method) >= 0); + buf = + self->field_history[self->history_count - 1 - + gst_deinterlace_method_get_latency (self->method)].buf; + timestamp = GST_BUFFER_TIMESTAMP (buf); + + gst_buffer_unref (gst_deinterlace_pop_history (self)); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + if (self->fields == GST_DEINTERLACE_ALL) + GST_BUFFER_DURATION (outbuf) = self->field_duration; + else + GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration; + + ret = gst_pad_push (self->srcpad, outbuf); + outbuf = NULL; + if (ret != GST_FLOW_OK) + return ret; + } + /* no calculation done: remove excess field */ + else if (self->field_history[cur_field_idx].flags == + PICTURE_INTERLACED_TOP && self->fields == GST_DEINTERLACE_BF) { + GST_DEBUG_OBJECT (self, "Removing unused top field"); + gst_buffer_unref (gst_deinterlace_pop_history (self)); + } + + cur_field_idx = self->history_count - fields_required; + if (self->history_count < fields_required) + break; + + /* deinterlace bottom_field */ + if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM + && self->fields == GST_DEINTERLACE_BF) || + self->fields == GST_DEINTERLACE_ALL) { + GST_DEBUG_OBJECT (self, "deinterlacing bottom field"); + + /* create new buffer */ + ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad, + GST_BUFFER_OFFSET_NONE, self->frame_size, + GST_PAD_CAPS (self->srcpad), &outbuf); + if (ret != GST_FLOW_OK) + return ret; + + /* do magic calculus */ + gst_deinterlace_method_deinterlace_frame (self->method, self, outbuf); + + g_assert (self->history_count - 1 - + gst_deinterlace_method_get_latency (self->method) >= 0); + buf = + self->field_history[self->history_count - 1 - + gst_deinterlace_method_get_latency (self->method)].buf; + timestamp = GST_BUFFER_TIMESTAMP (buf); + + gst_buffer_unref (gst_deinterlace_pop_history (self)); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + if (self->fields == GST_DEINTERLACE_ALL) + GST_BUFFER_DURATION (outbuf) = self->field_duration; + else + GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration; + + ret = gst_pad_push (self->srcpad, outbuf); + outbuf = NULL; + + if (ret != GST_FLOW_OK) + return ret; + } + /* no calculation done: remove excess field */ + else if (self->field_history[cur_field_idx].flags == + PICTURE_INTERLACED_BOTTOM && self->fields == GST_DEINTERLACE_TF) { + GST_DEBUG_OBJECT (self, "Removing unused bottom field"); + gst_buffer_unref (gst_deinterlace_pop_history (self)); + } + } + + GST_DEBUG_OBJECT (self, "----chain end ----\n\n"); + + return ret; +} + +static gint +gst_greatest_common_divisor (gint a, gint b) +{ + while (b != 0) { + int temp = a; + + a = b; + b = temp % b; + } + + return ABS (a); +} + +static gboolean +gst_fraction_double (gint * n_out, gint * d_out, gboolean half) +{ + gint n, d, gcd; + + n = *n_out; + d = *d_out; + + if (d == 0) + return FALSE; + + if (n == 0 || (n == G_MAXINT && d == 1)) + return TRUE; + + gcd = gst_greatest_common_divisor (n, d); + n /= gcd; + d /= gcd; + + if (!half) { + if (G_MAXINT / 2 >= ABS (n)) { + n *= 2; + } else if (d >= 2) { + d /= 2; + } else { + return FALSE; + } + } else { + if (G_MAXINT / 2 >= ABS (d)) { + d *= 2; + } else if (n >= 2) { + n /= 2; + } else { + return FALSE; + } + } + + *n_out = n; + *d_out = d; + + return TRUE; +} + +static GstCaps * +gst_deinterlace_getcaps (GstPad * pad) +{ + GstCaps *ret; + GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad)); + GstPad *otherpad; + gint len; + const GstCaps *ourcaps; + GstCaps *peercaps; + + GST_OBJECT_LOCK (self); + + otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; + + ourcaps = gst_pad_get_pad_template_caps (pad); + peercaps = gst_pad_peer_get_caps (otherpad); + + if (peercaps) { + ret = gst_caps_intersect (ourcaps, peercaps); + gst_caps_unref (peercaps); + } else { + ret = gst_caps_copy (ourcaps); + } + + GST_OBJECT_UNLOCK (self); + + if ((self->interlaced || self->mode == GST_DEINTERLACE_MODE_INTERLACED) && + self->fields == GST_DEINTERLACE_ALL + && self->mode != GST_DEINTERLACE_MODE_DISABLED) { + for (len = gst_caps_get_size (ret); len > 0; len--) { + GstStructure *s = gst_caps_get_structure (ret, len - 1); + const GValue *val; + + val = gst_structure_get_value (s, "framerate"); + if (!val) + continue; + + if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) { + gint n, d; + + n = gst_value_get_fraction_numerator (val); + d = gst_value_get_fraction_denominator (val); + + if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { + goto error; + } + + gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL); + } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) { + const GValue *min, *max; + GValue nrange = { 0, }, nmin = { + 0,}, nmax = { + 0,}; + gint n, d; + + g_value_init (&nrange, GST_TYPE_FRACTION_RANGE); + g_value_init (&nmin, GST_TYPE_FRACTION); + g_value_init (&nmax, GST_TYPE_FRACTION); + + min = gst_value_get_fraction_range_min (val); + max = gst_value_get_fraction_range_max (val); + + n = gst_value_get_fraction_numerator (min); + d = gst_value_get_fraction_denominator (min); + + if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { + g_value_unset (&nrange); + g_value_unset (&nmax); + g_value_unset (&nmin); + goto error; + } + + gst_value_set_fraction (&nmin, n, d); + + n = gst_value_get_fraction_numerator (max); + d = gst_value_get_fraction_denominator (max); + + if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { + g_value_unset (&nrange); + g_value_unset (&nmax); + g_value_unset (&nmin); + goto error; + } + + gst_value_set_fraction (&nmax, n, d); + gst_value_set_fraction_range (&nrange, &nmin, &nmax); + + gst_structure_set_value (s, "framerate", &nrange); + + g_value_unset (&nmin); + g_value_unset (&nmax); + g_value_unset (&nrange); + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + const GValue *lval; + GValue nlist = { 0, }; + GValue nval = { 0, }; + gint i; + + g_value_init (&nlist, GST_TYPE_LIST); + for (i = gst_value_list_get_size (val); i > 0; i--) { + gint n, d; + + lval = gst_value_list_get_value (val, i); + + if (G_VALUE_TYPE (lval) != GST_TYPE_FRACTION) + continue; + + n = gst_value_get_fraction_numerator (lval); + d = gst_value_get_fraction_denominator (lval); + + /* Double/Half the framerate but if this fails simply + * skip this value from the list */ + if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { + continue; + } + + g_value_init (&nval, GST_TYPE_FRACTION); + + gst_value_set_fraction (&nval, n, d); + gst_value_list_append_value (&nlist, &nval); + g_value_unset (&nval); + } + gst_structure_set_value (s, "framerate", &nlist); + g_value_unset (&nlist); + } + } + } + + GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret); + + return ret; + +error: + GST_ERROR_OBJECT (pad, "Unable to transform peer caps"); + gst_caps_unref (ret); + return NULL; +} + +static gboolean +gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps) +{ + gboolean res = TRUE; + GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad)); + GstPad *otherpad; + GstStructure *structure; + GstVideoFormat fmt; + guint32 fourcc; + GstCaps *othercaps; + + otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; + + structure = gst_caps_get_structure (caps, 0); + + res = gst_structure_get_int (structure, "width", &self->frame_width); + res &= gst_structure_get_int (structure, "height", &self->frame_height); + res &= + gst_structure_get_fraction (structure, "framerate", &self->frame_rate_n, + &self->frame_rate_d); + res &= gst_structure_get_fourcc (structure, "format", &fourcc); + res &= gst_video_format_parse_caps_interlaced (caps, &self->interlaced); + if (!res) + goto invalid_caps; + + if ((self->interlaced || self->mode == GST_DEINTERLACE_MODE_INTERLACED) && + self->fields == GST_DEINTERLACE_ALL + && self->mode != GST_DEINTERLACE_MODE_DISABLED) { + gint fps_n = self->frame_rate_n, fps_d = self->frame_rate_d; + + if (!gst_fraction_double (&fps_n, &fps_d, otherpad != self->srcpad)) + goto invalid_caps; + + othercaps = gst_caps_copy (caps); + + gst_caps_set_simple (othercaps, "framerate", GST_TYPE_FRACTION, fps_n, + fps_d, NULL); + } else { + othercaps = gst_caps_ref (caps); + } + + if (!gst_pad_set_caps (otherpad, othercaps)) + goto caps_not_accepted; + gst_caps_unref (othercaps); + + self->field_height = self->frame_height / 2; + + fmt = gst_video_format_from_fourcc (fourcc); + + /* TODO: only true if fields are subbuffers of interlaced frames, + change when the buffer-fields concept has landed */ + self->field_stride = + gst_video_format_get_row_stride (fmt, 0, self->frame_width) * 2; + + /* in bytes */ + self->row_stride = + gst_video_format_get_row_stride (fmt, 0, self->frame_width); + self->frame_size = + gst_video_format_get_size (fmt, self->frame_width, self->frame_height); + + if (self->fields == GST_DEINTERLACE_ALL && otherpad == self->srcpad) + self->field_duration = + gst_util_uint64_scale (GST_SECOND, self->frame_rate_d, + self->frame_rate_n); + else + self->field_duration = + gst_util_uint64_scale (GST_SECOND, self->frame_rate_d, + 2 * self->frame_rate_n); + + GST_DEBUG_OBJECT (self, "Set caps: %" GST_PTR_FORMAT, caps); + +done: + + gst_object_unref (self); + return res; + +invalid_caps: + res = FALSE; + GST_ERROR_OBJECT (pad, "Invalid caps: %" GST_PTR_FORMAT, caps); + goto done; + +caps_not_accepted: + res = FALSE; + GST_ERROR_OBJECT (pad, "Caps not accepted: %" GST_PTR_FORMAT, othercaps); + gst_caps_unref (othercaps); + goto done; +} + +static gboolean +gst_deinterlace_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad)); + + GST_LOG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + case GST_EVENT_EOS: + case GST_EVENT_NEWSEGMENT: + gst_deinterlace_reset_history (self); + + /* fall through */ + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (self); + return res; +} + +static GstStateChangeReturn +gst_deinterlace_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstDeinterlace *self = GST_DEINTERLACE (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret != GST_STATE_CHANGE_SUCCESS) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_deinterlace_reset (self); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + default: + break; + } + + return ret; +} + +static gboolean +gst_deinterlace_src_event (GstPad * pad, GstEvent * event) +{ + GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad)); + gboolean res; + + GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (self); + + return res; +} + +static gboolean +gst_deinterlace_src_query (GstPad * pad, GstQuery * query) +{ + GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad)); + gboolean res = FALSE; + + GST_LOG_OBJECT (self, "%s query", GST_QUERY_TYPE_NAME (query)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + if ((self->interlaced || self->mode == GST_DEINTERLACE_MODE_INTERLACED) + && self->mode != GST_DEINTERLACE_MODE_DISABLED) { + GstClockTime min, max; + gboolean live; + GstPad *peer; + + if ((peer = gst_pad_get_peer (self->sinkpad))) { + if ((res = gst_pad_query (peer, query))) { + GstClockTime latency; + gint fields_required = 0; + gint method_latency = 0; + + if (self->method) { + fields_required = + gst_deinterlace_method_get_fields_required (self->method); + method_latency = + gst_deinterlace_method_get_latency (self->method); + } + + gst_query_parse_latency (query, &live, &min, &max); + + GST_DEBUG_OBJECT (self, "Peer latency: min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + /* add our own latency */ + latency = (fields_required + method_latency) * self->field_duration; + + GST_DEBUG_OBJECT (self, "Our latency: min %" GST_TIME_FORMAT + ", max %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency), GST_TIME_ARGS (latency)); + + min += latency; + if (max != GST_CLOCK_TIME_NONE) + max += latency; + else + max = latency; + + GST_DEBUG_OBJECT (self, "Calculated total latency : min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + gst_query_set_latency (query, live, min, max); + } + gst_object_unref (peer); + } else { + res = gst_pad_query_default (pad, query); + } + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (self); + return res; +} + +static const GstQueryType * +gst_deinterlace_src_query_types (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_LATENCY, + GST_QUERY_NONE + }; + return types; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (deinterlace_debug, "deinterlace", 0, "Deinterlacer"); + + oil_init (); + + if (!gst_element_register (plugin, "deinterlace", GST_RANK_NONE, + GST_TYPE_DEINTERLACE)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "deinterlace", + "Deinterlacer", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN); diff --git a/gst/deinterlace/gstdeinterlace.h b/gst/deinterlace/gstdeinterlace.h new file mode 100644 index 00000000..d4bbf0bb --- /dev/null +++ b/gst/deinterlace/gstdeinterlace.h @@ -0,0 +1,259 @@ +/* + * GStreamer + * Copyright (C) 2005 Martin Eikermann + * Copyright (C) 2008-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_DEINTERLACE_H__ +#define __GST_DEINTERLACE_H__ + +#include +#include +#include +#include +#include + +#ifdef HAVE_GCC_ASM +#if defined(HAVE_CPU_I386) || defined(HAVE_CPU_X86_64) +#define BUILD_X86_ASM +#endif +#endif + +G_BEGIN_DECLS + +#define GST_TYPE_DEINTERLACE \ + (gst_deinterlace_get_type()) +#define GST_DEINTERLACE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEINTERLACE,GstDeinterlace)) +#define GST_DEINTERLACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEINTERLACE,GstDeinterlace)) +#define GST_IS_DEINTERLACE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEINTERLACE)) +#define GST_IS_DEINTERLACE_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEINTERLACE)) + +typedef struct _GstDeinterlace GstDeinterlace; +typedef struct _GstDeinterlaceClass GstDeinterlaceClass; + +#define GST_TYPE_DEINTERLACE_METHOD (gst_deinterlace_method_get_type ()) +#define GST_IS_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD)) +#define GST_IS_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD)) +#define GST_DEINTERLACE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass)) +#define GST_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethod)) +#define GST_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass)) +#define GST_DEINTERLACE_METHOD_CAST(obj) ((GstDeinterlaceMethod*)(obj)) + +typedef struct _GstDeinterlaceMethod GstDeinterlaceMethod; +typedef struct _GstDeinterlaceMethodClass GstDeinterlaceMethodClass; + +/* + * This structure defines the deinterlacer plugin. + */ + +struct _GstDeinterlaceMethod { + GstObject parent; +}; + +struct _GstDeinterlaceMethodClass { + GstObjectClass parent_class; + guint fields_required; + guint latency; + + void (*deinterlace_frame) (GstDeinterlaceMethod *self, GstDeinterlace * parent, GstBuffer *outbuf); + + const gchar *name; + const gchar *nick; +}; + +GType gst_deinterlace_method_get_type (void); + +#define GST_TYPE_DEINTERLACE_SIMPLE_METHOD (gst_deinterlace_simple_method_get_type ()) +#define GST_IS_DEINTERLACE_SIMPLE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD)) +#define GST_IS_DEINTERLACE_SIMPLE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_SIMPLE_METHOD)) +#define GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethodClass)) +#define GST_DEINTERLACE_SIMPLE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethod)) +#define GST_DEINTERLACE_SIMPLE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethodClass)) +#define GST_DEINTERLACE_SIMPLE_METHOD_CAST(obj) ((GstDeinterlaceSimpleMethod*)(obj)) + +typedef struct _GstDeinterlaceSimpleMethod GstDeinterlaceSimpleMethod; +typedef struct _GstDeinterlaceSimpleMethodClass GstDeinterlaceSimpleMethodClass; +typedef struct _GstDeinterlaceScanlineData GstDeinterlaceScanlineData; + +/* + * This structure defines the simple deinterlacer plugin. + */ + +struct _GstDeinterlaceScanlineData { + guint8 *tt0, *t0, *m0, *b0, *bb0; + guint8 *tt1, *t1, *m1, *b1, *bb1; + guint8 *tt2, *t2, *m2, *b2, *bb2; + guint8 *tt3, *t3, *m3, *b3, *bb3; + gboolean bottom_field; +}; + +/** + * For interpolate_scanline the input is: + * + * | t-3 t-2 t-1 t + * | Field 3 | Field 2 | Field 1 | Field 0 | + * | TT3 | | TT1 | | + * | | T2 | | T0 | + * | M3 | | M1 | | + * | | B2 | | B0 | + * | BB3 | | BB1 | | + * + * For copy_scanline the input is: + * + * | t-3 t-2 t-1 t + * | Field 3 | Field 2 | Field 1 | Field 0 | + * | | TT2 | | TT0 | + * | T3 | | T1 | | + * | | M2 | | M0 | + * | B3 | | B1 | | + * | | BB2 | | BB0 | + * + * All other values are NULL. + */ + +struct _GstDeinterlaceSimpleMethod { + GstDeinterlaceMethod parent; +}; + +struct _GstDeinterlaceSimpleMethodClass { + GstDeinterlaceMethodClass parent_class; + + void (*interpolate_scanline) (GstDeinterlaceMethod *self, GstDeinterlace * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width); + void (*copy_scanline) (GstDeinterlaceMethod *self, GstDeinterlace * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width); +}; + +GType gst_deinterlace_simple_method_get_type (void); + + +#define MAX_FIELD_HISTORY 10 + +#define PICTURE_PROGRESSIVE 0 +#define PICTURE_INTERLACED_BOTTOM 1 +#define PICTURE_INTERLACED_TOP 2 +#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP) + +typedef struct +{ + /* pointer to the start of data for this field */ + GstBuffer *buf; + /* see PICTURE_ flags */ + guint flags; +} GstPicture; + +typedef enum +{ + GST_DEINTERLACE_TOMSMOCOMP, + GST_DEINTERLACE_GREEDY_H, + GST_DEINTERLACE_GREEDY_L, + GST_DEINTERLACE_VFIR, + GST_DEINTERLACE_LINEAR, + GST_DEINTERLACE_LINEAR_BLEND, + GST_DEINTERLACE_SCALER_BOB, + GST_DEINTERLACE_WEAVE, + GST_DEINTERLACE_WEAVE_TFF, + GST_DEINTERLACE_WEAVE_BFF +} GstDeinterlaceMethods; + +typedef enum +{ + GST_DEINTERLACE_ALL, /* All (missing data is interp.) */ + GST_DEINTERLACE_TF, /* Top Fields Only */ + GST_DEINTERLACE_BF /* Bottom Fields Only */ +} GstDeinterlaceFields; + +typedef enum +{ + GST_DEINTERLACE_LAYOUT_AUTO, + GST_DEINTERLACE_LAYOUT_TFF, + GST_DEINTERLACE_LAYOUT_BFF +} GstDeinterlaceFieldLayout; + +typedef enum { + GST_DEINTERLACE_MODE_AUTO, + GST_DEINTERLACE_MODE_INTERLACED, + GST_DEINTERLACE_MODE_DISABLED +} GstDeinterlaceMode; + +struct _GstDeinterlace +{ + GstElement parent; + + GstPad *srcpad, *sinkpad; + + /* */ + + GstDeinterlaceMode mode; + + GstDeinterlaceFieldLayout field_layout; + + guint frame_size; + gint frame_rate_n, frame_rate_d; + gboolean interlaced; + + /* Duration of one field */ + GstClockTime field_duration; + + GstDeinterlaceFields fields; + + GstDeinterlaceMethods method_id; + GstDeinterlaceMethod *method; + + /* The most recent pictures + PictureHistory[0] is always the most recent. + Pointers are NULL if the picture in question isn't valid, e.g. because + the program just started or a picture was skipped. + */ + GstPicture field_history[MAX_FIELD_HISTORY]; + guint history_count; + + /* Number of bytes of actual data in each scanline. May be less than + OverlayPitch since the overlay's scanlines might have alignment + requirements. Generally equal to FrameWidth * 2. + */ + guint row_stride; + + /* Number of pixels in each scanline. */ + gint frame_width; + + /* Number of scanlines per frame. */ + gint frame_height; + + /* Number of scanlines per field. FrameHeight / 2, mostly for + cleanliness so we don't have to keep dividing FrameHeight by 2. + */ + gint field_height; + + /* distance between lines in image + need not match the pixel width + */ + guint field_stride; +}; + +struct _GstDeinterlaceClass +{ + GstElementClass parent_class; +}; + +GType gst_deinterlace_get_type (void); + +G_END_DECLS +#endif /* __GST_DEINTERLACE_H__ */ diff --git a/gst/deinterlace/tvtime/greedy.c b/gst/deinterlace/tvtime/greedy.c new file mode 100644 index 00000000..293d82fa --- /dev/null +++ b/gst/deinterlace/tvtime/greedy.c @@ -0,0 +1,488 @@ +/* + * + * GStreamer + * Copyright (c) 2000 Tom Barry All rights reserved. + * mmx.h port copyright (c) 2002 Billy Biggs . + * + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Relicensed for GStreamer from GPL to LGPL with permit from Tom Barry + * and Billy Biggs. + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" + +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L)) +#define GST_IS_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L)) +#define GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass)) +#define GST_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyL)) +#define GST_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass)) +#define GST_DEINTERLACE_METHOD_GREEDY_L_CAST(obj) ((GstDeinterlaceMethodGreedyL*)(obj)) + +GType gst_deinterlace_method_greedy_l_get_type (void); + +typedef struct +{ + GstDeinterlaceMethod parent; + + guint max_comb; +} GstDeinterlaceMethodGreedyL; + +typedef struct +{ + GstDeinterlaceMethodClass parent_class; + void (*scanline) (GstDeinterlaceMethodGreedyL * self, uint8_t * L2, + uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size); +} GstDeinterlaceMethodGreedyLClass; + +// 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 inline void +deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self, + uint8_t * m0, uint8_t * t1, + uint8_t * b1, uint8_t * m2, uint8_t * output, int width) +{ + int avg, l2_diff, lp2_diff, max, min, best; + guint max_comb = self->max_comb; + + // L2 == m0 + // L1 == t1 + // L3 == b1 + // LP2 == m2 + + while (width--) { + avg = (*t1 + *b1) / 2; + + l2_diff = ABS (*m0 - avg); + lp2_diff = ABS (*m2 - avg); + + if (l2_diff > lp2_diff) + best = *m2; + else + best = *m0; + + max = MAX (*t1, *b1); + min = MIN (*t1, *b1); + + if (max < 256 - max_comb) + max += max_comb; + else + max = 255; + + if (min > max_comb) + min -= max_comb; + else + min = 0; + + *output = CLAMP (best, min, max); + + // Advance to the next set of pixels. + output += 1; + m0 += 1; + t1 += 1; + b1 += 1; + m2 += 1; + } +} + +#ifdef BUILD_X86_ASM +#include "mmx.h" +static void +deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self, + uint8_t * m0, uint8_t * t1, + uint8_t * b1, uint8_t * m2, uint8_t * output, int width) +{ + mmx_t MaxComb; + mmx_t ShiftMask; + + // How badly do we let it weave? 0-255 + MaxComb.ub[0] = self->max_comb; + MaxComb.ub[1] = self->max_comb; + MaxComb.ub[2] = self->max_comb; + MaxComb.ub[3] = self->max_comb; + MaxComb.ub[4] = self->max_comb; + MaxComb.ub[5] = self->max_comb; + MaxComb.ub[6] = self->max_comb; + MaxComb.ub[7] = self->max_comb; + + ShiftMask.ub[0] = 0x7f; + ShiftMask.ub[1] = 0x7f; + ShiftMask.ub[2] = 0x7f; + ShiftMask.ub[3] = 0x7f; + ShiftMask.ub[4] = 0x7f; + ShiftMask.ub[5] = 0x7f; + ShiftMask.ub[6] = 0x7f; + ShiftMask.ub[7] = 0x7f; + + // L2 == m0 + // L1 == t1 + // L3 == b1 + // LP2 == m2 + + movq_m2r (MaxComb, mm6); + + for (; width > 7; width -= 8) { + 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 + movq_r2r (mm3, mm5); // L3 + psrlw_i2r (1, mm4); // L1/2 + pand_m2r (ShiftMask, mm4); + psrlw_i2r (1, mm5); // L3/2 + pand_m2r (ShiftMask, mm5); + paddusb_r2r (mm5, 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) + + // 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_r2r (mm6, mm2); // increase max by diff + psubusb_r2r (mm6, 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 + + movq_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; + } + emms (); + if (width > 0) + deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output, + width); +} + +#include "sse.h" + +static void +deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL * + self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, + uint8_t * output, int width) +{ + mmx_t MaxComb; + + // How badly do we let it weave? 0-255 + MaxComb.ub[0] = self->max_comb; + MaxComb.ub[1] = self->max_comb; + MaxComb.ub[2] = self->max_comb; + MaxComb.ub[3] = self->max_comb; + MaxComb.ub[4] = self->max_comb; + MaxComb.ub[5] = self->max_comb; + MaxComb.ub[6] = self->max_comb; + MaxComb.ub[7] = self->max_comb; + + // L2 == m0 + // L1 == t1 + // L3 == b1 + // LP2 == m2 + + movq_m2r (MaxComb, mm6); + + for (; width > 7; width -= 8) { + 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) + + // 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 + pxor_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 + pmaxub_r2r (mm3, mm2); // now = Max(L1,L3) + + pminub_r2r (mm1, mm3); // now = Min(L1,L3) + + // allow the value to be above the high or below the low by amt of MaxComb + paddusb_r2r (mm6, mm2); // increase max by diff + psubusb_r2r (mm6, mm3); // lower min by diff + + + pmaxub_r2r (mm3, mm4); // now = Max(best,Min(L1,L3) + pminub_r2r (mm4, mm2); // now = Min( Max(best, Min(L1,L3)), L2 )=L2 clipped + + movq_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; + } + emms (); + + if (width > 0) + deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output, + width); +} + +#endif + +static void +deinterlace_frame_di_greedy (GstDeinterlaceMethod * d_method, + GstDeinterlace * object, GstBuffer * outbuf) +{ + GstDeinterlaceMethodGreedyL *self = + GST_DEINTERLACE_METHOD_GREEDY_L (d_method); + GstDeinterlaceMethodGreedyLClass *klass = + GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self); + int InfoIsOdd = 0; + int Line; + unsigned int Pitch = object->field_stride; + unsigned char *L1; // ptr to Line1, of 3 + unsigned char *L2; // ptr to Line2, the weave line + unsigned char *L3; // ptr to Line3 + + unsigned char *L2P; // ptr to prev Line2 + unsigned char *Dest = GST_BUFFER_DATA (outbuf); + + // copy first even line no matter what, and the first odd line if we're + // processing an EVEN field. (note diff from other deint rtns.) + + if (object->field_history[object->history_count - 1].flags == + PICTURE_INTERLACED_BOTTOM) { + InfoIsOdd = 1; + + L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); + L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf); + L3 = L1 + Pitch; + L2P = + GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf); + + // copy first even line + oil_memcpy (Dest, L1, object->row_stride); + Dest += object->row_stride; + } else { + InfoIsOdd = 0; + L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); + L2 = GST_BUFFER_DATA (object->field_history[object->history_count - + 1].buf) + Pitch; + L3 = L1 + Pitch; + L2P = + GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) + + Pitch; + + // copy first even line + oil_memcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf), + object->row_stride); + Dest += object->row_stride; + // then first odd line + oil_memcpy (Dest, L1, object->row_stride); + Dest += object->row_stride; + } + + for (Line = 0; Line < (object->field_height - 1); ++Line) { + klass->scanline (self, L2, L1, L3, L2P, Dest, object->row_stride); + Dest += object->row_stride; + oil_memcpy (Dest, L3, object->row_stride); + Dest += object->row_stride; + + L1 += Pitch; + L2 += Pitch; + L3 += Pitch; + L2P += Pitch; + } + + if (InfoIsOdd) { + oil_memcpy (Dest, L2, object->row_stride); + } +} + + +G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l, + GST_TYPE_DEINTERLACE_METHOD); + +enum +{ + ARG_0, + ARG_MAX_COMB +}; + +static void +gst_deinterlace_method_greedy_l_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object); + + switch (prop_id) { + case ARG_MAX_COMB: + self->max_comb = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_deinterlace_method_greedy_l_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object); + + switch (prop_id) { + case ARG_MAX_COMB: + g_value_set_uint (value, self->max_comb); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass * + klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; +#ifdef BUILD_X86_ASM + guint cpu_flags = oil_cpu_get_flags (); +#endif + + gobject_class->set_property = gst_deinterlace_method_greedy_l_set_property; + gobject_class->get_property = gst_deinterlace_method_greedy_l_get_property; + + g_object_class_install_property (gobject_class, ARG_MAX_COMB, + g_param_spec_uint ("max-comb", + "Max comb", + "Max Comb", 0, 255, 15, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + dim_class->fields_required = 4; + dim_class->deinterlace_frame = deinterlace_frame_di_greedy; + dim_class->name = "Motion Adaptive: Simple Detection"; + dim_class->nick = "greedyl"; + dim_class->latency = 1; + +#ifdef BUILD_X86_ASM + if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { + klass->scanline = deinterlace_greedy_packed422_scanline_mmxext; + } else if (cpu_flags & OIL_IMPL_FLAG_MMX) { + klass->scanline = deinterlace_greedy_packed422_scanline_mmx; + } else { + klass->scanline = deinterlace_greedy_packed422_scanline_c; + } +#else + klass->scanline = deinterlace_greedy_packed422_scanline_c; +#endif +} + +static void +gst_deinterlace_method_greedy_l_init (GstDeinterlaceMethodGreedyL * self) +{ + self->max_comb = 15; +} diff --git a/gst/deinterlace/tvtime/greedyh.asm b/gst/deinterlace/tvtime/greedyh.asm new file mode 100644 index 00000000..86e97c58 --- /dev/null +++ b/gst/deinterlace/tvtime/greedyh.asm @@ -0,0 +1,250 @@ +/* + * + * GStreamer + * Copyright (c) 2001 Tom Barry. All rights reserved. + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/* + * Relicensed for GStreamer from GPL to LGPL with permit from Tom Barry. + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + + +#include "x86-64_macros.inc" + +void +FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P, + uint8_t * Dest, int size) +{ + + // in tight loop some vars are accessed faster in local storage + int64_t YMask = 0x00ff00ff00ff00ffull; // to keep only luma + int64_t UVMask = 0xff00ff00ff00ff00ull; // to keep only chroma + int64_t ShiftMask = 0xfefefefefefefefeull; // to avoid shifting chroma to luma + int64_t QW256 = 0x0100010001000100ull; // 4 256's + int64_t MaxComb; + int64_t MotionThreshold; + int64_t MotionSense; + int64_t i; + long LoopCtr; + long oldbx; + + int64_t QW256B; + int64_t LastAvg = 0; //interp value from left qword + + // FIXME: Use C implementation if the width is not a multiple of 4 + // Do something more optimal later + if (size % 8 != 0) + greedyDScaler_C (self, L1, L2, L3, L2P, Dest, size); + + // Set up our two parms that are actually evaluated for each pixel + i = self->max_comb; + MaxComb = + i << 56 | i << 48 | i << 40 | i << 32 | i << 24 | i << 16 | i << 8 | i; + + i = self->motion_threshold; // scale to range of 0-257 + MotionThreshold = i << 48 | i << 32 | i << 16 | i | UVMask; + + i = self->motion_sense; // scale to range of 0-257 + MotionSense = i << 48 | i << 32 | i << 16 | i; + + i = 0xffffffff - 256; + QW256B = i << 48 | i << 32 | i << 16 | i; // save a couple instr on PMINSW instruct. + + LoopCtr = size / 8 - 1; // there are LineLength / 8 qwords per line but do 1 less, adj at end of loop + + // For ease of reading, the comments below assume that we're operating on an odd + // field (i.e., that InfoIsOdd is true). Assume the obvious for even lines.. + __asm__ __volatile__ ( + // save ebx (-fPIC) + MOVX " %%" XBX ", %[oldbx]\n\t" + MOVX " %[L1], %%" XAX "\n\t" + LEAX " 8(%%" XAX "), %%" XBX "\n\t" // next qword needed by DJR + MOVX " %[L3], %%" XCX "\n\t" + SUBX " %%" XAX ", %%" XCX "\n\t" // carry L3 addr as an offset + MOVX " %[L2P], %%" XDX "\n\t" + MOVX " %[L2], %%" XSI "\n\t" + MOVX " %[Dest], %%" XDI "\n\t" // DL1 if Odd or DL2 if Even + + ".align 8\n\t" + "1:\n\t" + "movq (%%" XSI "), %%mm0\n\t" // L2 - the newest weave pixel value + "movq (%%" XAX "), %%mm1\n\t" // L1 - the top pixel + "movq (%%" XDX "), %%mm2\n\t" // L2P - the prev weave pixel + "movq (%%" XAX ", %%" XCX "), %%mm3\n\t" // L3, next odd row + "movq %%mm1, %%mm6\n\t" // L1 - get simple single pixel interp + + // pavgb mm6, mm3 // use macro below + V_PAVGB ("%%mm6", "%%mm3", "%%mm4", "%[ShiftMask]") + + // DJR - Diagonal Jaggie Reduction + // In the event that we are going to use an average (Bob) pixel we do not want a jagged + // stair step effect. To combat this we avg in the 2 horizontally adjacen pixels into the + // interpolated Bob mix. This will do horizontal smoothing for only the Bob'd pixels. + + "movq %[LastAvg], %%mm4\n\t" // the bob value from prev qword in row + "movq %%mm6, %[LastAvg]\n\t" // save for next pass + "psrlq $48, %%mm4\n\t" // right justify 1 pixel + "movq %%mm6, %%mm7\n\t" // copy of simple bob pixel + "psllq $16, %%mm7\n\t" // left justify 3 pixels + "por %%mm7, %%mm4\n\t" // and combine + "movq (%%" XBX "), %%mm5\n\t" // next horiz qword from L1 + // pavgb mm5, qword ptr[ebx+ecx] // next horiz qword from L3, use macro below + + V_PAVGB ("%%mm5", "(%%" XBX ",%%" XCX ")", "%%mm7", "%[ShiftMask]") + "psllq $48, %%mm5\n\t" // left just 1 pixel + "movq %%mm6, %%mm7\n\t" // another copy of simple bob pixel + "psrlq $16, %%mm7\n\t" // right just 3 pixels + "por %%mm7, %%mm5\n\t" // combine + // pavgb mm4, mm5 // avg of forward and prev by 1 pixel, use macro + V_PAVGB ("%%mm4", "%%mm5", "%%mm5", "%[ShiftMask]") // mm5 gets modified if MMX + // pavgb mm6, mm4 // avg of center and surround interp vals, use macro + V_PAVGB ("%%mm6", "%%mm4", "%%mm7", "%[ShiftMask]") + + // Don't do any more averaging than needed for mmx. It hurts performance and causes rounding errors. +#ifndef IS_MMX + // pavgb mm4, mm6 // 1/4 center, 3/4 adjacent + V_PAVGB ("%%mm4", "%%mm6", "%%mm7", "%[ShiftMask]") + // pavgb mm6, mm4 // 3/8 center, 5/8 adjacent + V_PAVGB ("%%mm6", "%%mm4", "%%mm7", "%[ShiftMask]") +#endif + + // get abs value of possible L2 comb + "movq %%mm6, %%mm4\n\t" // work copy of interp val + "movq %%mm2, %%mm7\n\t" // L2 + "psubusb %%mm4, %%mm7\n\t" // L2 - avg + "movq %%mm4, %%mm5\n\t" // avg + "psubusb %%mm2, %%mm5\n\t" // avg - L2 + "por %%mm7, %%mm5\n\t" // abs(avg-L2) + + // get abs value of possible L2P comb + "movq %%mm0, %%mm7\n\t" // L2P + "psubusb %%mm4, %%mm7\n\t" // L2P - avg + "psubusb %%mm0, %%mm4\n\t" // avg - L2P + "por %%mm7, %%mm4\n\t" // abs(avg-L2P) + + // use L2 or L2P depending upon which makes smaller comb + "psubusb %%mm5, %%mm4\n\t" // see if it goes to zero + "psubusb %%mm5, %%mm5\n\t" // 0 + "pcmpeqb %%mm5, %%mm4\n\t" // if (mm4=0) then FF else 0 + "pcmpeqb %%mm4, %%mm5\n\t" // opposite of mm4 + + // if Comb(L2P) <= Comb(L2) then mm4=ff, mm5=0 else mm4=0, mm5 = 55 + "pand %%mm2, %%mm5\n\t" // use L2 if mm5 == ff, else 0 + "pand %%mm0, %%mm4\n\t" // use L2P if mm4 = ff, else 0 + "por %%mm5, %%mm4\n\t" // may the best win + + // Inventory: at this point we have the following values: + // mm0 = L2P (or L2) + // mm1 = L1 + // mm2 = L2 (or L2P) + // mm3 = L3 + // mm4 = the best of L2,L2P weave pixel, base upon comb + // mm6 = the avg interpolated value, if we need to use it + // Let's measure movement, as how much the weave pixel has changed + + "movq %%mm2, %%mm7\n\t" + "psubusb %%mm0, %%mm2\n\t" + "psubusb %%mm7, %%mm0\n\t" + "por %%mm2, %%mm0\n\t" // abs value of change, used later + + // Now lets clip our chosen value to be not outside of the range + // of the high/low range L1-L3 by more than MaxComb. + // This allows some comb but limits the damages and also allows more + // detail than a boring oversmoothed clip. + + "movq %%mm1, %%mm2\n\t" // copy L1 + // pmaxub mm2, mm3 // use macro + V_PMAXUB ("%%mm2", "%%mm3") // now = Max(L1,L3) + "movq %%mm1, %%mm5\n\t" // copy L1 + // pminub mm5, mm3 // now = Min(L1,L3), use macro + V_PMINUB ("%%mm5", "%%mm3", "%%mm7") + + // allow the value to be above the high or below the low by amt of MaxComb + "psubusb %[MaxComb], %%mm5\n\t" // lower min by diff + "paddusb %[MaxComb], %%mm2\n\t" // increase max by diff + // pmaxub mm4, mm5 // now = Max(best,Min(L1,L3) use macro + V_PMAXUB ("%%mm4", "%%mm5") + // pminub mm4, mm2 // now = Min( Max(best, Min(L1,L3), L2 )=L2 clipped + V_PMINUB ("%%mm4", "%%mm2", "%%mm7") + + // Blend weave pixel with bob pixel, depending on motion val in mm0 + "psubusb %[MotionThreshold], %%mm0\n\t" // test Threshold, clear chroma change >>>?? + "pmullw %[MotionSense], %%mm0\n\t" // mul by user factor, keep low 16 bits + "movq %[QW256], %%mm7\n\t" +#ifdef IS_MMXEXT + "pminsw %%mm7, %%mm0\n\t" // max = 256 +#else + "paddusw %[QW256B], %%mm0\n\t" // add, may sat at fff.. + "psubusw %[QW256B], %%mm0\n\t" // now = Min(L1,256) +#endif + "psubusw %%mm0, %%mm7\n\t" // so the 2 sum to 256, weighted avg + "movq %%mm4, %%mm2\n\t" // save weave chroma info before trashing + "pand %[YMask], %%mm4\n\t" // keep only luma from calc'd value + "pmullw %%mm7, %%mm4\n\t" // use more weave for less motion + "pand %[YMask], %%mm6\n\t" // keep only luma from calc'd value + "pmullw %%mm0, %%mm6\n\t" // use more bob for large motion + "paddusw %%mm6, %%mm4\n\t" // combine + "psrlw $8, %%mm4\n\t" // div by 256 to get weighted avg + // chroma comes from weave pixel + "pand %[UVMask], %%mm2\n\t" // keep chroma + "por %%mm4, %%mm2\n\t" // and combine + V_MOVNTQ ("(%%" XDI ")", "%%mm2") // move in our clipped best, use macro + // bump ptrs and loop + LEAX " 8(%%" XAX "), %%" XAX "\n\t" + LEAX " 8(%%" XBX "), %%" XBX "\n\t" + LEAX " 8(%%" XDX "), %%" XDX "\n\t" + LEAX " 8(%%" XDI "), %%" XDI "\n\t" + LEAX " 8(%%" XSI "), %%" XSI "\n\t" + DECX " %[LoopCtr]\n\t" + + "jg 1b\n\t" // loop if not to last line + // note P-III default assumes backward branches taken + "jl 1f\n\t" // done + MOVX " %%" XAX ", %%" XBX "\n\t" // sharpness lookahead 1 byte only, be wrong on 1 + "jmp 1b\n\t" + + "1:\n\t" + MOVX " %[oldbx], %%" XBX "\n\t" + "emms\n\t": /* no outputs */ + + :[LastAvg] "m" (LastAvg), + [L1] "m" (L1), + [L3] "m" (L3), + [L2P] "m" (L2P), + [L2] "m" (L2), + [Dest] "m" (Dest), + [ShiftMask] "m" (ShiftMask), + [MaxComb] "m" (MaxComb), + [MotionThreshold] "m" (MotionThreshold), + [MotionSense] "m" (MotionSense), + [QW256B] "m" (QW256B), + [YMask] "m" (YMask), + [UVMask] "m" (UVMask), + [LoopCtr] "m" (LoopCtr), + [QW256] "m" (QW256), + [oldbx] "m" (oldbx) + : XAX, XCX, XDX, XSI, XDI, + "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", +#ifdef __MMX__ + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", +#endif + "memory", "cc"); +} diff --git a/gst/deinterlace/tvtime/greedyh.c b/gst/deinterlace/tvtime/greedyh.c new file mode 100644 index 00000000..5d050ce0 --- /dev/null +++ b/gst/deinterlace/tvtime/greedyh.c @@ -0,0 +1,420 @@ +/* + * + * GStreamer + * Copyright (C) 2004 Billy Biggs + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs. + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "greedyhmacros.h" + +#include +#include "_stdint.h" +#include + +#include "gst/gst.h" +#include "plugins.h" +#include "gstdeinterlace.h" + +#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H)) +#define GST_IS_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H)) +#define GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass)) +#define GST_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyH)) +#define GST_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass)) +#define GST_DEINTERLACE_METHOD_GREEDY_H_CAST(obj) ((GstDeinterlaceMethodGreedyH*)(obj)) + +GType gst_deinterlace_method_greedy_h_get_type (void); + +typedef struct +{ + GstDeinterlaceMethod parent; + + guint max_comb, motion_threshold, motion_sense; +} GstDeinterlaceMethodGreedyH; + +typedef struct +{ + GstDeinterlaceMethodClass parent_class; + void (*scanline) (GstDeinterlaceMethodGreedyH * self, uint8_t * L2, + uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size); +} GstDeinterlaceMethodGreedyHClass; + +void +greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2, + uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size) +{ + int Pos; + uint8_t l1_l, l1_1_l, l3_l, l3_1_l; + uint8_t l1_c, l1_1_c, l3_c, l3_1_c; + uint8_t avg_l, avg_c, avg_l_1, avg_c_1; + uint8_t avg_l__1 = 0, avg_c__1 = 0; + uint8_t avg_s_l, avg_s_c; + uint8_t avg_sc_l, avg_sc_c; + uint8_t best_l, best_c; + uint16_t mov_l; + uint8_t out_l, out_c; + uint8_t l2_l, l2_c, lp2_l, lp2_c; + uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff; + uint8_t min_l, min_c, max_l, max_c; + guint max_comb = self->max_comb; + guint motion_sense = self->motion_sense; + guint motion_threshold = self->motion_threshold; + + for (Pos = 0; Pos < size; Pos += 2) { + l1_l = L1[0]; + l1_c = L1[1]; + l3_l = L3[0]; + l3_c = L3[1]; + + if (Pos == size - 1) { + l1_1_l = l1_l; + l1_1_c = l1_c; + l3_1_l = l3_l; + l3_1_c = l3_c; + } else { + l1_1_l = L1[2]; + l1_1_c = L1[3]; + l3_1_l = L3[2]; + l3_1_c = L3[3]; + } + + /* Average of L1 and L3 */ + avg_l = (l1_l + l3_l) / 2; + avg_c = (l1_c + l3_c) / 2; + + if (Pos == 0) { + avg_l__1 = avg_l; + avg_c__1 = avg_c; + } + + /* Average of next L1 and next L3 */ + avg_l_1 = (l1_1_l + l3_1_l) / 2; + avg_c_1 = (l1_1_c + l3_1_c) / 2; + + /* Calculate average of one pixel forward and previous */ + avg_s_l = (avg_l__1 + avg_l_1) / 2; + avg_s_c = (avg_c__1 + avg_c_1) / 2; + + /* Calculate average of center and surrounding pixels */ + avg_sc_l = (avg_l + avg_s_l) / 2; + avg_sc_c = (avg_c + avg_s_c) / 2; + + /* move forward */ + avg_l__1 = avg_l; + avg_c__1 = avg_c; + + /* Get best L2/L2P, i.e. least diff from above average */ + l2_l = L2[0]; + l2_c = L2[1]; + lp2_l = L2P[0]; + lp2_c = L2P[1]; + + l2_l_diff = ABS (l2_l - avg_sc_l); + l2_c_diff = ABS (l2_c - avg_sc_c); + + lp2_l_diff = ABS (lp2_l - avg_sc_l); + lp2_c_diff = ABS (lp2_c - avg_sc_c); + + if (l2_l_diff > lp2_l_diff) + best_l = lp2_l; + else + best_l = l2_l; + + if (l2_c_diff > lp2_c_diff) + best_c = lp2_c; + else + best_c = l2_c; + + /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */ + max_l = MAX (l1_l, l3_l); + min_l = MIN (l1_l, l3_l); + + if (max_l < 256 - max_comb) + max_l += max_comb; + else + max_l = 255; + + if (min_l > max_comb) + min_l -= max_comb; + else + min_l = 0; + + max_c = MAX (l1_c, l3_c); + min_c = MIN (l1_c, l3_c); + + if (max_c < 256 - max_comb) + max_c += max_comb; + else + max_c = 255; + + if (min_c > max_comb) + min_c -= max_comb; + else + min_c = 0; + + out_l = CLAMP (best_l, min_l, max_l); + out_c = CLAMP (best_c, min_c, max_c); + + /* Do motion compensation for luma, i.e. how much + * the weave pixel differs */ + mov_l = ABS (l2_l - lp2_l); + if (mov_l > motion_threshold) + mov_l -= motion_threshold; + else + mov_l = 0; + + mov_l = mov_l * motion_sense; + if (mov_l > 256) + mov_l = 256; + + /* Weighted sum on clipped weave pixel and average */ + out_l = (out_l * (256 - mov_l) + avg_sc_l * mov_l) / 256; + + Dest[0] = out_l; + Dest[1] = out_c; + + Dest += 2; + L1 += 2; + L2 += 2; + L3 += 2; + L2P += 2; + } +} + +#ifdef BUILD_X86_ASM + +#define IS_MMXEXT +#define SIMD_TYPE MMXEXT +#define FUNCT_NAME greedyDScaler_MMXEXT +#include "greedyh.asm" +#undef SIMD_TYPE +#undef IS_MMXEXT +#undef FUNCT_NAME + +#define IS_3DNOW +#define SIMD_TYPE 3DNOW +#define FUNCT_NAME greedyDScaler_3DNOW +#include "greedyh.asm" +#undef SIMD_TYPE +#undef IS_3DNOW +#undef FUNCT_NAME + +#define IS_MMX +#define SIMD_TYPE MMX +#define FUNCT_NAME greedyDScaler_MMX +#include "greedyh.asm" +#undef SIMD_TYPE +#undef IS_MMX +#undef FUNCT_NAME + +#endif + +static void +deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method, + GstDeinterlace * object, GstBuffer * outbuf) +{ + GstDeinterlaceMethodGreedyH *self = + GST_DEINTERLACE_METHOD_GREEDY_H (d_method); + GstDeinterlaceMethodGreedyHClass *klass = + GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self); + int InfoIsOdd = 0; + int Line; + unsigned int Pitch = object->field_stride; + + unsigned char *L1; // ptr to Line1, of 3 + unsigned char *L2; // ptr to Line2, the weave line + unsigned char *L3; // ptr to Line3 + + unsigned char *L2P; // ptr to prev Line2 + unsigned char *Dest = GST_BUFFER_DATA (outbuf); + + // copy first even line no matter what, and the first odd line if we're + // processing an EVEN field. (note diff from other deint rtns.) + + if (object->field_history[object->history_count - 1].flags == + PICTURE_INTERLACED_BOTTOM) { + InfoIsOdd = 1; + + L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); + L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf); + L3 = L1 + Pitch; + L2P = + GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf); + + // copy first even line + oil_memcpy (Dest, L1, object->row_stride); + Dest += object->row_stride; + } else { + InfoIsOdd = 0; + L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); + L2 = GST_BUFFER_DATA (object->field_history[object->history_count - + 1].buf) + Pitch; + L3 = L1 + Pitch; + L2P = + GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) + + Pitch; + + // copy first even line + oil_memcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf), + object->row_stride); + Dest += object->row_stride; + // then first odd line + oil_memcpy (Dest, L1, object->row_stride); + Dest += object->row_stride; + } + + for (Line = 0; Line < (object->field_height - 1); ++Line) { + klass->scanline (self, L1, L2, L3, L2P, Dest, object->row_stride); + Dest += object->row_stride; + oil_memcpy (Dest, L3, object->row_stride); + Dest += object->row_stride; + + L1 += Pitch; + L2 += Pitch; + L3 += Pitch; + L2P += Pitch; + } + + if (InfoIsOdd) { + oil_memcpy (Dest, L2, object->row_stride); + } +} + +G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h, + GST_TYPE_DEINTERLACE_METHOD); + +enum +{ + ARG_0, + ARG_MAX_COMB, + ARG_MOTION_THRESHOLD, + ARG_MOTION_SENSE +}; + +static void +gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object); + + switch (prop_id) { + case ARG_MAX_COMB: + self->max_comb = g_value_get_uint (value); + break; + case ARG_MOTION_THRESHOLD: + self->motion_threshold = g_value_get_uint (value); + break; + case ARG_MOTION_SENSE: + self->motion_sense = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object); + + switch (prop_id) { + case ARG_MAX_COMB: + g_value_set_uint (value, self->max_comb); + break; + case ARG_MOTION_THRESHOLD: + g_value_set_uint (value, self->motion_threshold); + break; + case ARG_MOTION_SENSE: + g_value_set_uint (value, self->motion_sense); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass * + klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; +#ifdef BUILD_X86_ASM + guint cpu_flags = oil_cpu_get_flags (); +#endif + + gobject_class->set_property = gst_deinterlace_method_greedy_h_set_property; + gobject_class->get_property = gst_deinterlace_method_greedy_h_get_property; + + g_object_class_install_property (gobject_class, ARG_MAX_COMB, + g_param_spec_uint ("max-comb", + "Max comb", + "Max Comb", 0, 255, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + g_object_class_install_property (gobject_class, ARG_MOTION_THRESHOLD, + g_param_spec_uint ("motion-threshold", + "Motion Threshold", + "Motion Threshold", + 0, 255, 25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + g_object_class_install_property (gobject_class, ARG_MOTION_SENSE, + g_param_spec_uint ("motion-sense", + "Motion Sense", + "Motion Sense", + 0, 255, 30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + dim_class->fields_required = 4; + dim_class->deinterlace_frame = deinterlace_frame_di_greedyh; + dim_class->name = "Motion Adaptive: Advanced Detection"; + dim_class->nick = "greedyh"; + dim_class->latency = 1; + +#ifdef BUILD_X86_ASM + if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { + klass->scanline = greedyDScaler_MMXEXT; + } else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) { + klass->scanline = greedyDScaler_3DNOW; + } else if (cpu_flags & OIL_IMPL_FLAG_MMX) { + klass->scanline = greedyDScaler_MMX; + } else { + klass->scanline = greedyDScaler_C; + } +#else + klass->scanline = greedyDScaler_C; +#endif +} + +static void +gst_deinterlace_method_greedy_h_init (GstDeinterlaceMethodGreedyH * self) +{ + self->max_comb = 5; + self->motion_threshold = 25; + self->motion_sense = 30; +} diff --git a/gst/deinterlace/tvtime/greedyhmacros.h b/gst/deinterlace/tvtime/greedyhmacros.h new file mode 100644 index 00000000..0386c28e --- /dev/null +++ b/gst/deinterlace/tvtime/greedyhmacros.h @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2001 Tom Barry. All rights reserved. +///////////////////////////////////////////////////////////////////////////// +// +// This file is subject to the terms of the GNU General Public License as +// published by the Free Software Foundation. A copy of this license is +// included with this software distribution in the file COPYING. If you +// do not have a copy, you may obtain a copy by writing to the Free +// Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +// +// This software 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 +// +///////////////////////////////////////////////////////////////////////////// + +// Define a few macros for CPU dependent instructions. +// I suspect I don't really understand how the C macro preprocessor works but +// this seems to get the job done. // TRB 7/01 + +// BEFORE USING THESE YOU MUST SET: + +// #define SIMD_TYPE MMXEXT (or MMX or 3DNOW) + +// some macros for pavgb instruction +// V_PAVGB(mmr1, mmr2, mmr work register, smask) mmr2 may = mmrw if you can trash it + +#define V_PAVGB_MMX(mmr1, mmr2, mmrw, smask) \ + "movq "mmr2", "mmrw"\n\t" \ + "pand "smask", "mmrw"\n\t" \ + "psrlw $1, "mmrw"\n\t" \ + "pand "smask", "mmr1"\n\t" \ + "psrlw $1, "mmr1"\n\t" \ + "paddusb "mmrw", "mmr1"\n\t" +#define V_PAVGB_MMXEXT(mmr1, mmr2, mmrw, smask) "pavgb "mmr2", "mmr1"\n\t" +#define V_PAVGB_3DNOW(mmr1, mmr2, mmrw, smask) "pavgusb "mmr2", "mmr1"\n\t" +#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SIMD_TYPE) +#define V_PAVGB2(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) +#define V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB_##simd_type(mmr1, mmr2, mmrw, smask) + +// some macros for pmaxub instruction +#define V_PMAXUB_MMX(mmr1, mmr2) \ + "psubusb "mmr2", "mmr1"\n\t" \ + "paddusb "mmr2", "mmr1"\n\t" +#define V_PMAXUB_MMXEXT(mmr1, mmr2) "pmaxub "mmr2", "mmr1"\n\t" +#define V_PMAXUB_3DNOW(mmr1, mmr2) V_PMAXUB_MMX(mmr1, mmr2) // use MMX version +#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SIMD_TYPE) +#define V_PMAXUB2(mmr1, mmr2, simd_type) V_PMAXUB3(mmr1, mmr2, simd_type) +#define V_PMAXUB3(mmr1, mmr2, simd_type) V_PMAXUB_##simd_type(mmr1, mmr2) + +// some macros for pminub instruction +// V_PMINUB(mmr1, mmr2, mmr work register) mmr2 may NOT = mmrw +#define V_PMINUB_MMX(mmr1, mmr2, mmrw) \ + "pcmpeqb "mmrw", "mmrw"\n\t" \ + "psubusb "mmr2", "mmrw"\n\t" \ + "paddusb "mmrw", "mmr1"\n\t" \ + "psubusb "mmrw", "mmr1"\n\t" +#define V_PMINUB_MMXEXT(mmr1, mmr2, mmrw) "pminub "mmr2", "mmr1"\n\t" +#define V_PMINUB_3DNOW(mmr1, mmr2, mmrw) V_PMINUB_MMX(mmr1, mmr2, mmrw) // use MMX version +#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SIMD_TYPE) +#define V_PMINUB2(mmr1, mmr2, mmrw, simd_type) V_PMINUB3(mmr1, mmr2, mmrw, simd_type) +#define V_PMINUB3(mmr1, mmr2, mmrw, simd_type) V_PMINUB_##simd_type(mmr1, mmr2, mmrw) + +// some macros for movntq instruction +// V_MOVNTQ(mmr1, mmr2) +#define V_MOVNTQ_MMX(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" +#define V_MOVNTQ_3DNOW(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" +#define V_MOVNTQ_MMXEXT(mmr1, mmr2) "movntq "mmr2", "mmr1"\n\t" +#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SIMD_TYPE) +#define V_MOVNTQ2(mmr1, mmr2, simd_type) V_MOVNTQ3(mmr1, mmr2, simd_type) +#define V_MOVNTQ3(mmr1, mmr2, simd_type) V_MOVNTQ_##simd_type(mmr1, mmr2) + +// end of macros + diff --git a/gst/deinterlace/tvtime/linear.c b/gst/deinterlace/tvtime/linear.c new file mode 100644 index 00000000..8a13d8a1 --- /dev/null +++ b/gst/deinterlace/tvtime/linear.c @@ -0,0 +1,214 @@ +/** + * Copyright (C) 2002 Billy Biggs . + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_LINEAR (gst_deinterlace_method_linear_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_LINEAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR)) +#define GST_IS_DEINTERLACE_METHOD_LINEAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR)) +#define GST_DEINTERLACE_METHOD_LINEAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR, GstDeinterlaceMethodLinearClass)) +#define GST_DEINTERLACE_METHOD_LINEAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR, GstDeinterlaceMethodLinear)) +#define GST_DEINTERLACE_METHOD_LINEAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR, GstDeinterlaceMethodLinearClass)) +#define GST_DEINTERLACE_METHOD_LINEAR_CAST(obj) ((GstDeinterlaceMethodLinear*)(obj)) + +GType gst_deinterlace_method_linear_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodLinear; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodLinearClass; + +static void +deinterlace_scanline_linear_c (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + gint i; + + width *= 2; + for (i = 0; i < width; i++) + out[i] = (scanlines->t0[i] + scanlines->b0[i]) / 2; +} + +#ifdef BUILD_X86_ASM +#include "mmx.h" +static void +deinterlace_scanline_linear_mmx (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + const mmx_t shiftmask = { 0xfefffefffefffeffULL }; /* To avoid shifting chroma to luma. */ + int i; + guint8 *bot = scanlines->b0, *top = scanlines->t0; + + for (i = width / 16; i; --i) { + movq_m2r (*bot, mm0); + movq_m2r (*top, mm1); + movq_m2r (*(bot + 8), mm2); + movq_m2r (*(top + 8), mm3); + movq_m2r (*(bot + 16), mm4); + movq_m2r (*(top + 16), mm5); + movq_m2r (*(bot + 24), mm6); + movq_m2r (*(top + 24), mm7); + pand_m2r (shiftmask, mm0); + pand_m2r (shiftmask, mm1); + pand_m2r (shiftmask, mm2); + pand_m2r (shiftmask, mm3); + pand_m2r (shiftmask, mm4); + pand_m2r (shiftmask, mm5); + pand_m2r (shiftmask, mm6); + pand_m2r (shiftmask, mm7); + psrlw_i2r (1, mm0); + psrlw_i2r (1, mm1); + psrlw_i2r (1, mm2); + psrlw_i2r (1, mm3); + psrlw_i2r (1, mm4); + psrlw_i2r (1, mm5); + psrlw_i2r (1, mm6); + psrlw_i2r (1, mm7); + paddb_r2r (mm1, mm0); + paddb_r2r (mm3, mm2); + paddb_r2r (mm5, mm4); + paddb_r2r (mm7, mm6); + movq_r2m (mm0, *out); + movq_r2m (mm2, *(out + 8)); + movq_r2m (mm4, *(out + 16)); + movq_r2m (mm6, *(out + 24)); + out += 32; + top += 32; + bot += 32; + } + width = (width & 0xf); + + for (i = width / 4; i; --i) { + movq_m2r (*bot, mm0); + movq_m2r (*top, mm1); + pand_m2r (shiftmask, mm0); + pand_m2r (shiftmask, mm1); + psrlw_i2r (1, mm0); + psrlw_i2r (1, mm1); + paddb_r2r (mm1, mm0); + movq_r2m (mm0, *out); + out += 8; + top += 8; + bot += 8; + } + width = width & 0x7; + + /* Handle last few pixels. */ + for (i = width * 2; i; --i) { + *out++ = ((*top++) + (*bot++)) >> 1; + } + + emms (); +} + +#include "sse.h" +static void +deinterlace_scanline_linear_mmxext (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + gint i; + guint8 *bot = scanlines->b0, *top = scanlines->t0; + + for (i = width / 16; i; --i) { + movq_m2r (*bot, mm0); + movq_m2r (*top, mm1); + movq_m2r (*(bot + 8), mm2); + movq_m2r (*(top + 8), mm3); + movq_m2r (*(bot + 16), mm4); + movq_m2r (*(top + 16), mm5); + movq_m2r (*(bot + 24), mm6); + movq_m2r (*(top + 24), mm7); + pavgb_r2r (mm1, mm0); + pavgb_r2r (mm3, mm2); + pavgb_r2r (mm5, mm4); + pavgb_r2r (mm7, mm6); + movntq_r2m (mm0, *out); + movntq_r2m (mm2, *(out + 8)); + movntq_r2m (mm4, *(out + 16)); + movntq_r2m (mm6, *(out + 24)); + out += 32; + top += 32; + bot += 32; + } + width = (width & 0xf); + + for (i = width / 4; i; --i) { + movq_m2r (*bot, mm0); + movq_m2r (*top, mm1); + pavgb_r2r (mm1, mm0); + movntq_r2m (mm0, *out); + out += 8; + top += 8; + bot += 8; + } + width = width & 0x7; + + /* Handle last few pixels. */ + for (i = width * 2; i; --i) { + *out++ = ((*top++) + (*bot++)) >> 1; + } + + emms (); +} + +#endif + +G_DEFINE_TYPE (GstDeinterlaceMethodLinear, gst_deinterlace_method_linear, + GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void +gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass * + klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; +#ifdef BUILD_X86_ASM + guint cpu_flags = oil_cpu_get_flags (); +#endif + + dim_class->fields_required = 1; + dim_class->name = "Television: Full resolution"; + dim_class->nick = "linear"; + dim_class->latency = 0; + + dism_class->interpolate_scanline = deinterlace_scanline_linear_c; + +#ifdef BUILD_X86_ASM + if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { + dism_class->interpolate_scanline = deinterlace_scanline_linear_mmxext; + } else if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { + dism_class->interpolate_scanline = deinterlace_scanline_linear_mmx; + } +#endif +} + +static void +gst_deinterlace_method_linear_init (GstDeinterlaceMethodLinear * self) +{ +} diff --git a/gst/deinterlace/tvtime/linearblend.c b/gst/deinterlace/tvtime/linearblend.c new file mode 100644 index 00000000..5ecffd6e --- /dev/null +++ b/gst/deinterlace/tvtime/linearblend.c @@ -0,0 +1,231 @@ +/** + * Linear blend deinterlacing plugin. The idea for this algorithm came + * from the linear blend deinterlacer which originated in the mplayer + * sources. + * + * Copyright (C) 2002 Billy Biggs . + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND (gst_deinterlace_method_linear_blend_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_LINEAR_BLEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND)) +#define GST_IS_DEINTERLACE_METHOD_LINEAR_BLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND)) +#define GST_DEINTERLACE_METHOD_LINEAR_BLEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND, GstDeinterlaceMethodLinearBlendClass)) +#define GST_DEINTERLACE_METHOD_LINEAR_BLEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND, GstDeinterlaceMethodLinearBlend)) +#define GST_DEINTERLACE_METHOD_LINEAR_BLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND, GstDeinterlaceMethodLinearBlendClass)) +#define GST_DEINTERLACE_METHOD_LINEAR_BLEND_CAST(obj) ((GstDeinterlaceMethodLinearBlend*)(obj)) + +GType gst_deinterlace_method_linear_blend_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodLinearBlend; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodLinearBlendClass; + + +static inline void +deinterlace_scanline_linear_blend_c (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + guint8 *t0 = scanlines->t0; + guint8 *b0 = scanlines->b0; + guint8 *m1 = scanlines->m1; + + width *= 2; + + while (width--) { + *out++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2; + } +} + +static inline void +deinterlace_scanline_linear_blend2_c (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + guint8 *m0 = scanlines->m0; + guint8 *t1 = scanlines->t1; + guint8 *b1 = scanlines->b1; + + width *= 2; + while (width--) { + *out++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2; + } +} + +#ifdef BUILD_X86_ASM +#include "mmx.h" +static inline void +deinterlace_scanline_linear_blend_mmx (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + guint8 *t0 = scanlines->t0; + guint8 *b0 = scanlines->b0; + guint8 *m1 = scanlines->m1; + gint 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, *out); + movd_r2m (mm5, *(out + 4)); + out += 8; + t0 += 8; + b0 += 8; + m1 += 8; + } + while (width--) { + *out++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2; + } + emms (); +} + +static inline void +deinterlace_scanline_linear_blend2_mmx (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + guint8 *m0 = scanlines->m0; + guint8 *t1 = scanlines->t1; + guint8 *b1 = scanlines->b1; + gint 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, *out); + movd_r2m (mm5, *(out + 4)); + out += 8; + t1 += 8; + b1 += 8; + m0 += 8; + } + while (width--) { + *out++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2; + } + emms (); +} + +#endif + +G_DEFINE_TYPE (GstDeinterlaceMethodLinearBlend, + gst_deinterlace_method_linear_blend, GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void + gst_deinterlace_method_linear_blend_class_init + (GstDeinterlaceMethodLinearBlendClass * klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; +#ifdef BUILD_X86_ASM + guint cpu_flags = oil_cpu_get_flags (); +#endif + + dim_class->fields_required = 2; + dim_class->name = "Blur: Temporal"; + dim_class->nick = "linearblend"; + dim_class->latency = 0; + + dism_class->interpolate_scanline = deinterlace_scanline_linear_blend_c; + dism_class->copy_scanline = deinterlace_scanline_linear_blend2_c; + +#ifdef BUILD_X86_ASM + if (cpu_flags & OIL_IMPL_FLAG_MMX) { + dism_class->interpolate_scanline = deinterlace_scanline_linear_blend_mmx; + dism_class->copy_scanline = deinterlace_scanline_linear_blend2_mmx; + } +#endif +} + +static void +gst_deinterlace_method_linear_blend_init (GstDeinterlaceMethodLinearBlend * + self) +{ +} diff --git a/gst/deinterlace/tvtime/mmx.h b/gst/deinterlace/tvtime/mmx.h new file mode 100644 index 00000000..3627e61b --- /dev/null +++ b/gst/deinterlace/tvtime/mmx.h @@ -0,0 +1,723 @@ +/* mmx.h + + MultiMedia eXtensions GCC interface library for IA32. + + To use this library, simply include this header file + and compile with GCC. You MUST have inlining enabled + in order for mmx_ok() to work; this can be done by + simply using -O on the GCC command line. + + Compiling with -DMMX_TRACE will cause detailed trace + output to be sent to stderr for each mmx operation. + This adds lots of code, and obviously slows execution to + a crawl, but can be very useful for debugging. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT + LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR ANY PARTICULAR PURPOSE. + + 1997-98 by H. Dietz and R. Fisher + + History: + 97-98* R.Fisher Early versions + 980501 R.Fisher Original Release + 980611* H.Dietz Rewrite, correctly implementing inlines, and + R.Fisher including direct register accesses. + 980616 R.Fisher Release of 980611 as 980616. + 980714 R.Fisher Minor corrections to Makefile, etc. + 980715 R.Fisher mmx_ok() now prevents optimizer from using + clobbered values. + mmx_ok() now checks if cpuid instruction is + available before trying to use it. + 980726* R.Fisher mm_support() searches for AMD 3DNow, Cyrix + Extended MMX, and standard MMX. It returns a + value which is positive if any of these are + supported, and can be masked with constants to + see which. mmx_ok() is now a call to this + 980726* R.Fisher Added i2r support for shift functions + 980919 R.Fisher Fixed AMD extended feature recognition bug. + 980921 R.Fisher Added definition/check for _MMX_H. + Added "float s[2]" to mmx_t for use with + 3DNow and EMMX. So same mmx_t can be used. + 981013 R.Fisher Fixed cpuid function 1 bug (looked at wrong reg) + Fixed psllq_i2r error in mmxtest.c + + * Unreleased (internal or interim) versions + + Notes: + It appears that the latest gas has the pand problem fixed, therefore + I'll undefine BROKEN_PAND by default. + String compares may be quicker than the multiple test/jumps in vendor + test sequence in mmx_ok(), but I'm not concerned with that right now. + + Acknowledgments: + Jussi Laako for pointing out the errors ultimately found to be + connected to the failure to notify the optimizer of clobbered values. + Roger Hardiman for reminding us that CPUID isn't everywhere, and that + someone may actually try to use this on a machine without CPUID. + Also for suggesting code for checking this. + Robert Dale for pointing out the AMD recognition bug. + Jimmy Mayfield and Carl Witty for pointing out the Intel recognition + bug. + Carl Witty for pointing out the psllq_i2r test bug. +*/ + +#ifndef _MMX_H +#define _MMX_H + +/*#define MMX_TRACE */ + +/* Warning: at this writing, the version of GAS packaged + with most Linux distributions does not handle the + parallel AND operation mnemonic correctly. If the + symbol BROKEN_PAND is defined, a slower alternative + coding will be used. If execution of mmxtest results + in an illegal instruction fault, define this symbol. +*/ +#undef BROKEN_PAND + + +/* The type of an value that fits in an MMX register + (note that long long constant values MUST be suffixed + by LL and unsigned long long values by ULL, lest + they be truncated by the compiler) +*/ +typedef union { + long long q; /* Quadword (64-bit) value */ + unsigned long long uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} mmx_t; + + +/* Function to test if multimedia instructions are supported... +*/ +inline extern int +mm_support(void) +{ + /* Returns 1 if MMX instructions are supported, + 3 if Cyrix MMX and Extended MMX instructions are supported + 5 if AMD MMX and 3DNow! instructions are supported + 0 if hardware does not support any of these + */ + register int rval = 0; + + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %%eax\n\t" + "push %%eax\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %%eax\n\t" + + /* ... Compare and test result */ + "xorl %%eax, %%ecx\n\t" + "testl $0x200000, %%ecx\n\t" + "jz NotSupported1\n\t" /* Nothing supported */ + + + /* Get standard CPUID information, and + go to a specific vendor section */ + "movl $0, %%eax\n\t" + "cpuid\n\t" + + /* Check for Intel */ + "cmpl $0x756e6547, %%ebx\n\t" + "jne TryAMD\n\t" + "cmpl $0x49656e69, %%edx\n\t" + "jne TryAMD\n\t" + "cmpl $0x6c65746e, %%ecx\n" + "jne TryAMD\n\t" + "jmp Intel\n\t" + + /* Check for AMD */ + "\nTryAMD:\n\t" + "cmpl $0x68747541, %%ebx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x69746e65, %%edx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x444d4163, %%ecx\n" + "jne TryCyrix\n\t" + "jmp AMD\n\t" + + /* Check for Cyrix */ + "\nTryCyrix:\n\t" + "cmpl $0x69727943, %%ebx\n\t" + "jne NotSupported2\n\t" + "cmpl $0x736e4978, %%edx\n\t" + "jne NotSupported3\n\t" + "cmpl $0x64616574, %%ecx\n\t" + "jne NotSupported4\n\t" + /* Drop through to Cyrix... */ + + + /* Cyrix Section */ + /* See if extended CPUID is supported */ + "movl $0x80000000, %%eax\n\t" + "cpuid\n\t" + "cmpl $0x80000000, %%eax\n\t" + "jl MMXtest\n\t" /* Try standard CPUID instead */ + + /* Extended CPUID supported, so get extended features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%eax\n\t" /* Test for MMX */ + "jz NotSupported5\n\t" /* MMX not supported */ + "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ + "jnz EMMXSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "EMMXSupported:\n\t" + "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ + "jmp Return\n\t" + + + /* AMD Section */ + "AMD:\n\t" + + /* See if extended CPUID is supported */ + "movl $0x80000000, %%eax\n\t" + "cpuid\n\t" + "cmpl $0x80000000, %%eax\n\t" + "jl MMXtest\n\t" /* Try standard CPUID instead */ + + /* Extended CPUID supported, so get extended features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported6\n\t" /* MMX not supported */ + "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ + "jnz ThreeDNowSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "ThreeDNowSupported:\n\t" + "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ + "jmp Return\n\t" + + + /* Intel Section */ + "Intel:\n\t" + + /* Check for MMX */ + "MMXtest:\n\t" + "movl $1, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported7\n\t" /* MMX Not supported */ + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\t" + + /* Nothing supported */ + "\nNotSupported1:\n\t" + "#movl $101, %0:\n\n\t" + "\nNotSupported2:\n\t" + "#movl $102, %0:\n\n\t" + "\nNotSupported3:\n\t" + "#movl $103, %0:\n\n\t" + "\nNotSupported4:\n\t" + "#movl $104, %0:\n\n\t" + "\nNotSupported5:\n\t" + "#movl $105, %0:\n\n\t" + "\nNotSupported6:\n\t" + "#movl $106, %0:\n\n\t" + "\nNotSupported7:\n\t" + "#movl $107, %0:\n\n\t" + "movl $0, %0:\n\n\t" + + "Return:\n\t" + : "=a" (rval) + : /* no input */ + : "eax", "ebx", "ecx", "edx" + ); + + /* Return */ + return(rval); +} + +/* Function to test if mmx instructions are supported... +*/ +inline extern int +mmx_ok(void) +{ + /* Returns 1 if MMX instructions are supported, 0 otherwise */ + return ( mm_support() & 0x1 ); +} + + +/* Helper functions for the instruction macros that follow... + (note that memory-to-register, m2r, instructions are nearly + as efficient as register-to-register, r2r, instructions; + however, memory-to-memory instructions are really simulated + as a convenience, and are only 1/3 as efficient) +*/ +#ifdef MMX_TRACE + +/* Include the stuff for printing a trace to stderr... +*/ + +#include + +#define mmx_i2r(op, imm, reg) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (imm); \ + fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \ + } + +#define mmx_m2r(op, mem, reg) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (mem); \ + fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \ + } + +#define mmx_r2m(op, reg, mem) \ + { \ + mmx_t mmx_trace; \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \ + mmx_trace = (mem); \ + fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ); \ + mmx_trace = (mem); \ + fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \ + } + +#define mmx_r2r(op, regs, regd) \ + { \ + mmx_t mmx_trace; \ + __asm__ __volatile__ ("movq %%" #regs ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=X" (mmx_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \ + } + +#define mmx_m2m(op, mems, memd) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (mems); \ + fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \ + mmx_trace = (memd); \ + fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=X" (memd) \ + : "X" (mems)); \ + mmx_trace = (memd); \ + fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \ + } + +#else + +/* These macros are a lot simpler without the tracing... +*/ + +#define mmx_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " $" #imm ", %%" #reg \ + : /* nothing */ \ + : /* nothing */); + +#define mmx_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) + +#define mmx_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define mmx_m2m(op, mems, memd) \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=m" (memd) \ + : "m" (mems)) + +#endif + + +/* 1x64 MOVe Quadword + (this is both a load and a store... + in fact, it is the only way to store) +*/ +#define movq_m2r(var, reg) mmx_m2r(movq, var, reg) +#define movq_r2m(reg, var) mmx_r2m(movq, reg, var) +#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd) +#define movq(vars, vard) \ + __asm__ __volatile__ ("movq %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* 1x32 MOVe Doubleword + (like movq, this is both load and store... + but is most useful for moving things between + mmx registers and ordinary registers) +*/ +#define movd_m2r(var, reg) mmx_m2r(movd, var, reg) +#define movd_r2m(reg, var) mmx_r2m(movd, reg, var) +#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd) +#define movd(vars, vard) \ + __asm__ __volatile__ ("movd %1, %%mm0\n\t" \ + "movd %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* 2x32, 4x16, and 8x8 Parallel ADDs +*/ +#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg) +#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd) +#define paddd(vars, vard) mmx_m2m(paddd, vars, vard) + +#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg) +#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd) +#define paddw(vars, vard) mmx_m2m(paddw, vars, vard) + +#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg) +#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd) +#define paddb(vars, vard) mmx_m2m(paddb, vars, vard) + + +/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic +*/ +#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg) +#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd) +#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard) + +#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) +#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) +#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard) + + +/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic +*/ +#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg) +#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd) +#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard) + +#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) +#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) +#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel SUBs +*/ +#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg) +#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd) +#define psubd(vars, vard) mmx_m2m(psubd, vars, vard) + +#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg) +#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd) +#define psubw(vars, vard) mmx_m2m(psubw, vars, vard) + +#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) +#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) +#define psubb(vars, vard) mmx_m2m(psubb, vars, vard) + + +/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic +*/ +#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg) +#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd) +#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard) + +#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) +#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) +#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard) + + +/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic +*/ +#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg) +#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd) +#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard) + +#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) +#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) +#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard) + + +/* 4x16 Parallel MULs giving Low 4x16 portions of results +*/ +#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg) +#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd) +#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard) + + +/* 4x16 Parallel MULs giving High 4x16 portions of results +*/ +#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg) +#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd) +#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard) + + +/* 4x16->2x32 Parallel Mul-ADD + (muls like pmullw, then adds adjacent 16-bit fields + in the multiply result to make the final 2x32 result) +*/ +#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) +#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) +#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard) + + +/* 1x64 bitwise AND +*/ +#ifdef BROKEN_PAND +#define pand_m2r(var, reg) \ + { \ + mmx_m2r(pandn, (mmx_t) -1LL, reg); \ + mmx_m2r(pandn, var, reg); \ + } +#define pand_r2r(regs, regd) \ + { \ + mmx_m2r(pandn, (mmx_t) -1LL, regd); \ + mmx_r2r(pandn, regs, regd); \ + } +#define pand(vars, vard) \ + { \ + movq_m2r(vard, mm0); \ + mmx_m2r(pandn, (mmx_t) -1LL, mm0); \ + mmx_m2r(pandn, vars, mm0); \ + movq_r2m(mm0, vard); \ + } +#else +#define pand_m2r(var, reg) mmx_m2r(pand, var, reg) +#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd) +#define pand(vars, vard) mmx_m2m(pand, vars, vard) +#endif + + +/* 1x64 bitwise AND with Not the destination +*/ +#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) +#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) +#define pandn(vars, vard) mmx_m2m(pandn, vars, vard) + + +/* 1x64 bitwise OR +*/ +#define por_m2r(var, reg) mmx_m2r(por, var, reg) +#define por_r2r(regs, regd) mmx_r2r(por, regs, regd) +#define por(vars, vard) mmx_m2m(por, vars, vard) + + +/* 1x64 bitwise eXclusive OR +*/ +#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg) +#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd) +#define pxor(vars, vard) mmx_m2m(pxor, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality + (resulting fields are either 0 or -1) +*/ +#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) +#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard) + +#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) +#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard) + +#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) +#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than + (resulting fields are either 0 or -1) +*/ +#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) +#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard) + +#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) +#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard) + +#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) +#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard) + + +/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical +*/ +#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg) +#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) +#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) +#define psllq(vars, vard) mmx_m2m(psllq, vars, vard) + +#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg) +#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) +#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) +#define pslld(vars, vard) mmx_m2m(pslld, vars, vard) + +#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg) +#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) +#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) +#define psllw(vars, vard) mmx_m2m(psllw, vars, vard) + + +/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical +*/ +#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg) +#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) +#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) +#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard) + +#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg) +#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) +#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) +#define psrld(vars, vard) mmx_m2m(psrld, vars, vard) + +#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg) +#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) +#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) +#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard) + + +/* 2x32 and 4x16 Parallel Shift Right Arithmetic +*/ +#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg) +#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) +#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) +#define psrad(vars, vard) mmx_m2m(psrad, vars, vard) + +#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg) +#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) +#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) +#define psraw(vars, vard) mmx_m2m(psraw, vars, vard) + + +/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate + (packs source and dest fields into dest in that order) +*/ +#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) +#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) +#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard) + +#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) +#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) +#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard) + + +/* 4x16->8x8 PACK and Unsigned Saturate + (packs source and dest fields into dest in that order) +*/ +#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) +#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) +#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard) + + +/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low + (interleaves low half of dest with low half of source + as padding in each result field) +*/ +#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) +#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) +#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard) + +#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) +#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) +#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard) + +#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) +#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) +#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard) + + +/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High + (interleaves high half of dest with high half of source + as padding in each result field) +*/ +#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) +#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) +#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard) + +#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) +#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) +#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard) + +#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) +#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) +#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard) + + +/* Empty MMx State + (used to clean-up when going from mmx to float use + of the registers that are shared by both; note that + there is no float-to-mmx operation needed, because + only the float tag word info is corruptible) +*/ +#ifdef MMX_TRACE + +#define emms() \ + { \ + fprintf(stderr, "emms()\n"); \ + __asm__ __volatile__ ("emms"); \ + } + +#else + +#define emms() __asm__ __volatile__ ("emms") + +#endif + +#endif diff --git a/gst/deinterlace/tvtime/plugins.h b/gst/deinterlace/tvtime/plugins.h new file mode 100644 index 00000000..8fb01af5 --- /dev/null +++ b/gst/deinterlace/tvtime/plugins.h @@ -0,0 +1,54 @@ +/* + * + * GStreamer + * Copyright (C) 2004 Billy Biggs + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs. + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + +#ifndef TVTIME_PLUGINS_H_INCLUDED +#define TVTIME_PLUGINS_H_INCLUDED + +#define GST_TYPE_DEINTERLACE_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ()) +#define GST_TYPE_DEINTERLACE_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ()) +#define GST_TYPE_DEINTERLACE_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ()) +#define GST_TYPE_DEINTERLACE_VFIR (gst_deinterlace_method_vfir_get_type ()) +#define GST_TYPE_DEINTERLACE_LINEAR (gst_deinterlace_method_linear_get_type ()) +#define GST_TYPE_DEINTERLACE_LINEAR_BLEND (gst_deinterlace_method_linear_blend_get_type ()) +#define GST_TYPE_DEINTERLACE_SCALER_BOB (gst_deinterlace_method_scaler_bob_get_type ()) +#define GST_TYPE_DEINTERLACE_WEAVE (gst_deinterlace_method_weave_get_type ()) +#define GST_TYPE_DEINTERLACE_WEAVE_TFF (gst_deinterlace_method_weave_tff_get_type ()) +#define GST_TYPE_DEINTERLACE_WEAVE_BFF (gst_deinterlace_method_weave_bff_get_type ()) + +GType gst_deinterlace_method_tomsmocomp_get_type (void); +GType gst_deinterlace_method_greedy_h_get_type (void); +GType gst_deinterlace_method_greedy_l_get_type (void); +GType gst_deinterlace_method_vfir_get_type (void); + +GType gst_deinterlace_method_linear_get_type (void); +GType gst_deinterlace_method_linear_blend_get_type (void); +GType gst_deinterlace_method_scaler_bob_get_type (void); +GType gst_deinterlace_method_weave_get_type (void); +GType gst_deinterlace_method_weave_tff_get_type (void); +GType gst_deinterlace_method_weave_bff_get_type (void); + +#endif /* TVTIME_PLUGINS_H_INCLUDED */ diff --git a/gst/deinterlace/tvtime/scalerbob.c b/gst/deinterlace/tvtime/scalerbob.c new file mode 100644 index 00000000..a7bca169 --- /dev/null +++ b/gst/deinterlace/tvtime/scalerbob.c @@ -0,0 +1,74 @@ +/** + * Double lines + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB (gst_deinterlace_method_scaler_bob_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_SCALER_BOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB)) +#define GST_IS_DEINTERLACE_METHOD_SCALER_BOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB)) +#define GST_DEINTERLACE_METHOD_SCALER_BOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB, GstDeinterlaceMethodScalerBobClass)) +#define GST_DEINTERLACE_METHOD_SCALER_BOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB, GstDeinterlaceMethodScalerBob)) +#define GST_DEINTERLACE_METHOD_SCALER_BOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB, GstDeinterlaceMethodScalerBobClass)) +#define GST_DEINTERLACE_METHOD_SCALER_BOB_CAST(obj) ((GstDeinterlaceMethodScalerBob*)(obj)) + +GType gst_deinterlace_method_scaler_bob_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodScalerBob; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodScalerBobClass; + + +static void +deinterlace_scanline_scaler_bob (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->t0, parent->row_stride); +} + +G_DEFINE_TYPE (GstDeinterlaceMethodScalerBob, gst_deinterlace_method_scaler_bob, + GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void +gst_deinterlace_method_scaler_bob_class_init (GstDeinterlaceMethodScalerBobClass + * klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; + + dim_class->fields_required = 1; + dim_class->name = "Double lines"; + dim_class->nick = "scalerbob"; + dim_class->latency = 0; + + dism_class->interpolate_scanline = deinterlace_scanline_scaler_bob; +} + +static void +gst_deinterlace_method_scaler_bob_init (GstDeinterlaceMethodScalerBob * self) +{ +} diff --git a/gst/deinterlace/tvtime/sse.h b/gst/deinterlace/tvtime/sse.h new file mode 100644 index 00000000..2e00ee0c --- /dev/null +++ b/gst/deinterlace/tvtime/sse.h @@ -0,0 +1,992 @@ +/* sse.h + + Streaming SIMD Extenstions (a.k.a. Katmai New Instructions) + GCC interface library for IA32. + + To use this library, simply include this header file + and compile with GCC. You MUST have inlining enabled + in order for sse_ok() to work; this can be done by + simply using -O on the GCC command line. + + Compiling with -DSSE_TRACE will cause detailed trace + output to be sent to stderr for each sse operation. + This adds lots of code, and obviously slows execution to + a crawl, but can be very useful for debugging. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT + LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR ANY PARTICULAR PURPOSE. + + 1999 by R. Fisher + Based on libmmx by H. Dietz and R. Fisher + + Notes: + This is still extremely alpha. + Because this library depends on an assembler which understands the + SSE opcodes, you probably won't be able to use this yet. + For now, do not use TRACE versions. These both make use + of the MMX registers, not the SSE registers. This will be resolved + at a later date. + ToDo: + Rewrite TRACE macros + Major Debugging Work +*/ + +#ifndef _SSE_H +#define _SSE_H + + + +/* The type of an value that fits in an SSE register + (note that long long constant values MUST be suffixed + by LL and unsigned long long values by ULL, lest + they be truncated by the compiler) +*/ +typedef union { + float sf[4]; /* Single-precision (32-bit) value */ +} __attribute__ ((aligned (16))) sse_t; /* On a 16 byte (128-bit) boundary */ + + +#if 0 +/* Function to test if multimedia instructions are supported... +*/ +inline extern int +mm_support(void) +{ + /* Returns 1 if MMX instructions are supported, + 3 if Cyrix MMX and Extended MMX instructions are supported + 5 if AMD MMX and 3DNow! instructions are supported + 9 if MMX and SSE instructions are supported + 0 if hardware does not support any of these + */ + register int rval = 0; + + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %%eax\n\t" + "push %%eax\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %%eax\n\t" + + /* ... Compare and test result */ + "xorl %%eax, %%ecx\n\t" + "testl $0x200000, %%ecx\n\t" + "jz NotSupported1\n\t" /* CPUID not supported */ + + + /* Get standard CPUID information, and + go to a specific vendor section */ + "movl $0, %%eax\n\t" + "cpuid\n\t" + + /* Check for Intel */ + "cmpl $0x756e6547, %%ebx\n\t" + "jne TryAMD\n\t" + "cmpl $0x49656e69, %%edx\n\t" + "jne TryAMD\n\t" + "cmpl $0x6c65746e, %%ecx\n" + "jne TryAMD\n\t" + "jmp Intel\n\t" + + /* Check for AMD */ + "\nTryAMD:\n\t" + "cmpl $0x68747541, %%ebx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x69746e65, %%edx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x444d4163, %%ecx\n" + "jne TryCyrix\n\t" + "jmp AMD\n\t" + + /* Check for Cyrix */ + "\nTryCyrix:\n\t" + "cmpl $0x69727943, %%ebx\n\t" + "jne NotSupported2\n\t" + "cmpl $0x736e4978, %%edx\n\t" + "jne NotSupported3\n\t" + "cmpl $0x64616574, %%ecx\n\t" + "jne NotSupported4\n\t" + /* Drop through to Cyrix... */ + + + /* Cyrix Section */ + /* See if extended CPUID level 80000001 is supported */ + /* The value of CPUID/80000001 for the 6x86MX is undefined + according to the Cyrix CPU Detection Guide (Preliminary + Rev. 1.01 table 1), so we'll check the value of eax for + CPUID/0 to see if standard CPUID level 2 is supported. + According to the table, the only CPU which supports level + 2 is also the only one which supports extended CPUID levels. + */ + "cmpl $0x2, %%eax\n\t" + "jne MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported (in theory), so get extended + features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%eax\n\t" /* Test for MMX */ + "jz NotSupported5\n\t" /* MMX not supported */ + "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ + "jnz EMMXSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "EMMXSupported:\n\t" + "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ + "jmp Return\n\t" + + + /* AMD Section */ + "AMD:\n\t" + + /* See if extended CPUID is supported */ + "movl $0x80000000, %%eax\n\t" + "cpuid\n\t" + "cmpl $0x80000000, %%eax\n\t" + "jl MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported, so get extended features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported6\n\t" /* MMX not supported */ + "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ + "jnz ThreeDNowSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "ThreeDNowSupported:\n\t" + "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ + "jmp Return\n\t" + + + /* Intel Section */ + "Intel:\n\t" + + /* Check for SSE */ + "SSEtest:\n\t" + "movl $1, %%eax\n\t" + "cpuid\n\t" + "testl $0x02000000, %%edx\n\t" /* Test for SSE */ + "jz MMXtest\n\t" /* SSE Not supported */ + "movl $9, %0:\n\n\t" /* SSE Supported */ + "jmp Return\n\t" + + /* Check for MMX */ + "MMXtest:\n\t" + "movl $1, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported7\n\t" /* MMX Not supported */ + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\t" + + /* Nothing supported */ + "\nNotSupported1:\n\t" + "#movl $101, %0:\n\n\t" + "\nNotSupported2:\n\t" + "#movl $102, %0:\n\n\t" + "\nNotSupported3:\n\t" + "#movl $103, %0:\n\n\t" + "\nNotSupported4:\n\t" + "#movl $104, %0:\n\n\t" + "\nNotSupported5:\n\t" + "#movl $105, %0:\n\n\t" + "\nNotSupported6:\n\t" + "#movl $106, %0:\n\n\t" + "\nNotSupported7:\n\t" + "#movl $107, %0:\n\n\t" + "movl $0, %0:\n\n\t" + + "Return:\n\t" + : "=a" (rval) + : /* no input */ + : "eax", "ebx", "ecx", "edx" + ); + + /* Return */ + return(rval); +} + +/* Function to test if sse instructions are supported... +*/ +inline extern int +sse_ok(void) +{ + /* Returns 1 if SSE instructions are supported, 0 otherwise */ + return ( (mm_support() & 0x8) >> 3 ); +} +#endif + + + +/* Helper functions for the instruction macros that follow... + (note that memory-to-register, m2r, instructions are nearly + as efficient as register-to-register, r2r, instructions; + however, memory-to-memory instructions are really simulated + as a convenience, and are only 1/3 as efficient) +*/ +#ifdef SSE_TRACE + +/* Include the stuff for printing a trace to stderr... +*/ + +#include + +#define sse_i2r(op, imm, reg) \ + { \ + sse_t sse_trace; \ + sse_trace.uq = (imm); \ + fprintf(stderr, #op "_i2r(" #imm "=0x%08x%08x, ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%08x%08x) => ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%08x%08x\n", \ + sse_trace.d[1], sse_trace.d[0]); \ + } + +#define sse_m2r(op, mem, reg) \ + { \ + sse_t sse_trace; \ + sse_trace = (mem); \ + fprintf(stderr, #op "_m2r(" #mem "=0x%08x%08x, ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%08x%08x) => ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #reg "=0x%08x%08x\n", \ + sse_trace.d[1], sse_trace.d[0]); \ + } + +#define sse_r2m(op, reg, mem) \ + { \ + sse_t sse_trace; \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #op "_r2m(" #reg "=0x%08x%08x, ", \ + sse_trace.d[1], sse_trace.d[0]); \ + sse_trace = (mem); \ + fprintf(stderr, #mem "=0x%08x%08x) => ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ); \ + sse_trace = (mem); \ + fprintf(stderr, #mem "=0x%08x%08x\n", \ + sse_trace.d[1], sse_trace.d[0]); \ + } + +#define sse_r2r(op, regs, regd) \ + { \ + sse_t sse_trace; \ + __asm__ __volatile__ ("movq %%" #regs ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #op "_r2r(" #regs "=0x%08x%08x, ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #regd "=0x%08x%08x) => ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=X" (sse_trace) \ + : /* nothing */ ); \ + fprintf(stderr, #regd "=0x%08x%08x\n", \ + sse_trace.d[1], sse_trace.d[0]); \ + } + +#define sse_m2m(op, mems, memd) \ + { \ + sse_t sse_trace; \ + sse_trace = (mems); \ + fprintf(stderr, #op "_m2m(" #mems "=0x%08x%08x, ", \ + sse_trace.d[1], sse_trace.d[0]); \ + sse_trace = (memd); \ + fprintf(stderr, #memd "=0x%08x%08x) => ", \ + sse_trace.d[1], sse_trace.d[0]); \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=X" (memd) \ + : "X" (mems)); \ + sse_trace = (memd); \ + fprintf(stderr, #memd "=0x%08x%08x\n", \ + sse_trace.d[1], sse_trace.d[0]); \ + } + +#else + +/* These macros are a lot simpler without the tracing... +*/ + +#define sse_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)) + +#define sse_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ) + +#define sse_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define sse_r2ri(op, regs, regd, imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +/* Load data from mems to xmmreg, operate on xmmreg, and store data to memd */ +#define sse_m2m(op, mems, memd, xmmreg) \ + __asm__ __volatile__ ("movups %0, %%xmm0\n\t" \ + #op " %1, %%xmm0\n\t" \ + "movups %%mm0, %0" \ + : "=X" (memd) \ + : "X" (mems)) + +#define sse_m2ri(op, mem, reg, subop) \ + __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ + : /* nothing */ \ + : "X" (mem)) + +#define sse_m2mi(op, mems, memd, xmmreg, subop) \ + __asm__ __volatile__ ("movups %0, %%xmm0\n\t" \ + #op " %1, %%xmm0, " #subop "\n\t" \ + "movups %%mm0, %0" \ + : "=X" (memd) \ + : "X" (mems)) +#endif + + + + +/* 1x128 MOVe Aligned four Packed Single-fp +*/ +#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) +#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) +#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) +#define movaps(vars, vard) \ + __asm__ __volatile__ ("movaps %1, %%mm0\n\t" \ + "movaps %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* 1x128 MOVe aligned Non-Temporal four Packed Single-fp +*/ +#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) + + +/* 1x64 MOVe Non-Temporal Quadword +*/ +#define movntq_r2m(mmreg, var) sse_r2m(movntq, mmreg, var) + + +/* 1x128 MOVe Unaligned four Packed Single-fp +*/ +#define movups_m2r(var, reg) sse_m2r(movups, var, reg) +#define movups_r2m(reg, var) sse_r2m(movups, reg, var) +#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) +#define movups(vars, vard) \ + __asm__ __volatile__ ("movups %1, %%mm0\n\t" \ + "movups %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* MOVe High to Low Packed Single-fp + high half of 4x32f (x) -> low half of 4x32f (y) +*/ +#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) + + +/* MOVe Low to High Packed Single-fp + low half of 4x32f (x) -> high half of 4x32f (y) +*/ +#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) + + +/* MOVe High Packed Single-fp + 2x32f -> high half of 4x32f +*/ +#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) +#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) +#define movhps(vars, vard) \ + __asm__ __volatile__ ("movhps %1, %%mm0\n\t" \ + "movhps %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* MOVe Low Packed Single-fp + 2x32f -> low half of 4x32f +*/ +#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) +#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) +#define movlps(vars, vard) \ + __asm__ __volatile__ ("movlps %1, %%mm0\n\t" \ + "movlps %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* MOVe Scalar Single-fp + lowest field of 4x32f (x) -> lowest field of 4x32f (y) +*/ +#define movss_m2r(var, reg) sse_m2r(movss, var, reg) +#define movss_r2m(reg, var) sse_r2m(movss, reg, var) +#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) +#define movss(vars, vard) \ + __asm__ __volatile__ ("movss %1, %%mm0\n\t" \ + "movss %%mm0, %0" \ + : "=X" (vard) \ + : "X" (vars)) + + +/* 4x16 Packed SHUFfle Word +*/ +#define pshufw_m2r(var, reg, index) sse_m2ri(pshufw, var, reg, index) +#define pshufw_r2r(regs, regd, index) sse_r2ri(pshufw, regs, regd, index) + + +/* 1x128 SHUFfle Packed Single-fp +*/ +#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) +#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) + + +/* ConVerT Packed signed Int32 to(2) Packed Single-fp +*/ +#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) +#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) + + +/* ConVerT Packed Single-fp to(2) Packed signed Int32 +*/ +#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) +#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) + + +/* ConVerT with Truncate Packed Single-fp to(2) Packed Int32 +*/ +#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) +#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) + + +/* ConVerT Signed Int32 to(2) Single-fp (Scalar) +*/ +#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) +#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) + + +/* ConVerT Scalar Single-fp to(2) Signed Int32 +*/ +#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + + +/* ConVerT with Truncate Scalar Single-fp to(2) Signed Int32 +*/ +#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + + +/* Parallel EXTRact Word from 4x16 +*/ +#define pextrw_r2r(mmreg, reg, field) sse_r2ri(pextrw, mmreg, reg, field) + + +/* Parallel INSeRt Word from 4x16 +*/ +#define pinsrw_r2r(reg, mmreg, field) sse_r2ri(pinsrw, reg, mmreg, field) + + + +/* MOVe MaSK from Packed Single-fp +*/ +#ifdef SSE_TRACE + #define movmskps(xmmreg, reg) \ + { \ + fprintf(stderr, "movmskps()\n"); \ + __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) \ + } +#else + #define movmskps(xmmreg, reg) \ + __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) +#endif + + +/* Parallel MOVe MaSK from mmx reg to 32-bit reg +*/ +#ifdef SSE_TRACE + #define pmovmskb(mmreg, reg) \ + { \ + fprintf(stderr, "movmskps()\n"); \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) \ + } +#else + #define pmovmskb(mmreg, reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) +#endif + + +/* MASKed MOVe from 8x8 to memory pointed to by (e)di register +*/ +#define maskmovq(mmregs, fieldreg) sse_r2ri(maskmovq, mmregs, fieldreg) + + + + +/* 4x32f Parallel ADDs +*/ +#define addps_m2r(var, reg) sse_m2r(addps, var, reg) +#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) +#define addps(vars, vard, xmmreg) sse_m2m(addps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel ADDs +*/ +#define addss_m2r(var, reg) sse_m2r(addss, var, reg) +#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) +#define addss(vars, vard, xmmreg) sse_m2m(addss, vars, vard, xmmreg) + + +/* 4x32f Parallel SUBs +*/ +#define subps_m2r(var, reg) sse_m2r(subps, var, reg) +#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) +#define subps(vars, vard, xmmreg) sse_m2m(subps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel SUBs +*/ +#define subss_m2r(var, reg) sse_m2r(subss, var, reg) +#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) +#define subss(vars, vard, xmmreg) sse_m2m(subss, vars, vard, xmmreg) + + +/* 8x8u -> 4x16u Packed Sum of Absolute Differences +*/ +#define psadbw_m2r(var, reg) sse_m2r(psadbw, var, reg) +#define psadbw_r2r(regs, regd) sse_r2r(psadbw, regs, regd) +#define psadbw(vars, vard, mmreg) sse_m2m(psadbw, vars, vard, mmreg) + + +/* 4x16u Parallel MUL High Unsigned +*/ +#define pmulhuw_m2r(var, reg) sse_m2r(pmulhuw, var, reg) +#define pmulhuw_r2r(regs, regd) sse_r2r(pmulhuw, regs, regd) +#define pmulhuw(vars, vard, mmreg) sse_m2m(pmulhuw, vars, vard, mmreg) + + +/* 4x32f Parallel MULs +*/ +#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) +#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) +#define mulps(vars, vard, xmmreg) sse_m2m(mulps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel MULs +*/ +#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) +#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) +#define mulss(vars, vard, xmmreg) sse_m2m(mulss, vars, vard, xmmreg) + + +/* 4x32f Parallel DIVs +*/ +#define divps_m2r(var, reg) sse_m2r(divps, var, reg) +#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) +#define divps(vars, vard, xmmreg) sse_m2m(divps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel DIVs +*/ +#define divss_m2r(var, reg) sse_m2r(divss, var, reg) +#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) +#define divss(vars, vard, xmmreg) sse_m2m(divss, vars, vard, xmmreg) + + +/* 4x32f Parallel Reciprocals +*/ +#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) +#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) +#define rcpps(vars, vard, xmmreg) sse_m2m(rcpps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel Reciprocals +*/ +#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) +#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) +#define rcpss(vars, vard, xmmreg) sse_m2m(rcpss, vars, vard, xmmreg) + + +/* 4x32f Parallel Square Root of Reciprocals +*/ +#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) +#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) +#define rsqrtps(vars, vard, xmmreg) sse_m2m(rsqrtps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel Square Root of Reciprocals +*/ +#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) +#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) +#define rsqrtss(vars, vard, xmmreg) sse_m2m(rsqrtss, vars, vard, xmmreg) + + +/* 4x32f Parallel Square Roots +*/ +#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) +#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) +#define sqrtps(vars, vard, xmmreg) sse_m2m(sqrtps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel Square Roots +*/ +#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) +#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) +#define sqrtss(vars, vard, xmmreg) sse_m2m(sqrtss, vars, vard, xmmreg) + + +/* 8x8u and 4x16u Parallel AVeraGe +*/ +#define pavgb_m2r(var, reg) sse_m2r(pavgb, var, reg) +#define pavgb_r2r(regs, regd) sse_r2r(pavgb, regs, regd) +#define pavgb(vars, vard, mmreg) sse_m2m(pavgb, vars, vard, mmreg) + +#define pavgw_m2r(var, reg) sse_m2r(pavgw, var, reg) +#define pavgw_r2r(regs, regd) sse_r2r(pavgw, regs, regd) +#define pavgw(vars, vard, mmreg) sse_m2m(pavgw, vars, vard, mmreg) + + +/* 1x128 bitwise AND +*/ +#define andps_m2r(var, reg) sse_m2r(andps, var, reg) +#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) +#define andps(vars, vard, xmmreg) sse_m2m(andps, vars, vard, xmmreg) + + +/* 1x128 bitwise AND with Not the destination +*/ +#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) +#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) +#define andnps(vars, vard, xmmreg) sse_m2m(andnps, vars, vard, xmmreg) + + +/* 1x128 bitwise OR +*/ +#define orps_m2r(var, reg) sse_m2r(orps, var, reg) +#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) +#define orps(vars, vard, xmmreg) sse_m2m(orps, vars, vard, xmmreg) + + +/* 1x128 bitwise eXclusive OR +*/ +#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) +#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) +#define xorps(vars, vard, xmmreg) sse_m2m(xorps, vars, vard, xmmreg) + + +/* 8x8u, 4x16, and 4x32f Parallel Maximum +*/ +#define pmaxub_m2r(var, reg) sse_m2r(pmaxub, var, reg) +#define pmaxub_r2r(regs, regd) sse_r2r(pmaxub, regs, regd) +#define pmaxub(vars, vard, mmreg) sse_m2m(pmaxub, vars, vard, mmreg) + +#define pmaxsw_m2r(var, reg) sse_m2r(pmaxsw, var, reg) +#define pmaxsw_r2r(regs, regd) sse_r2r(pmaxsw, regs, regd) +#define pmaxsw(vars, vard, mmreg) sse_m2m(pmaxsw, vars, vard, mmreg) + +#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) +#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) +#define maxps(vars, vard, xmmreg) sse_m2m(maxps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel Maximum +*/ +#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) +#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) +#define maxss(vars, vard, xmmreg) sse_m2m(maxss, vars, vard, xmmreg) + + +/* 8x8u, 4x16, and 4x32f Parallel Minimum +*/ +#define pminub_m2r(var, reg) sse_m2r(pminub, var, reg) +#define pminub_r2r(regs, regd) sse_r2r(pminub, regs, regd) +#define pminub(vars, vard, mmreg) sse_m2m(pminub, vars, vard, mmreg) + +#define pminsw_m2r(var, reg) sse_m2r(pminsw, var, reg) +#define pminsw_r2r(regs, regd) sse_r2r(pminsw, regs, regd) +#define pminsw(vars, vard, mmreg) sse_m2m(pminsw, vars, vard, mmreg) + +#define minps_m2r(var, reg) sse_m2r(minps, var, reg) +#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) +#define minps(vars, vard, xmmreg) sse_m2m(minps, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Parallel Minimum +*/ +#define minss_m2r(var, reg) sse_m2r(minss, var, reg) +#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) +#define minss(vars, vard, xmmreg) sse_m2m(minss, vars, vard, xmmreg) + + +/* 4x32f Parallel CoMPares + (resulting fields are either 0 or -1) +*/ +#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) +#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) +#define cmpps(vars, vard, op, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, op) + +#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) +#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) +#define cmpeqps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 0) + +#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) +#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) +#define cmpltps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 1) + +#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) +#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) +#define cmpleps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 2) + +#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) +#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) +#define cmpunordps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 3) + +#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) +#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) +#define cmpneqps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 4) + +#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) +#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) +#define cmpnltps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 5) + +#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) +#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) +#define cmpnleps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 6) + +#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) +#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) +#define cmpordps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 7) + + +/* Lowest Field of 4x32f Parallel CoMPares + (resulting fields are either 0 or -1) +*/ +#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) +#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) +#define cmpss(vars, vard, op, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, op) + +#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) +#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) +#define cmpeqss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 0) + +#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) +#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) +#define cmpltss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 1) + +#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) +#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) +#define cmpless(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 2) + +#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) +#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) +#define cmpunordss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 3) + +#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) +#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) +#define cmpneqss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 4) + +#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) +#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) +#define cmpnltss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 5) + +#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) +#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) +#define cmpnless(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 6) + +#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) +#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) +#define cmpordss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 7) + + +/* Lowest Field of 4x32f Parallel CoMPares to set EFLAGS + (resulting fields are either 0 or -1) +*/ +#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) +#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) +#define comiss(vars, vard, xmmreg) sse_m2m(comiss, vars, vard, xmmreg) + + +/* Lowest Field of 4x32f Unordered Parallel CoMPares to set EFLAGS + (resulting fields are either 0 or -1) +*/ +#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) +#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) +#define ucomiss(vars, vard, xmmreg) sse_m2m(ucomiss, vars, vard, xmmreg) + + +/* 2-(4x32f) -> 4x32f UNPaCK Low Packed Single-fp + (interleaves low half of dest with low half of source + as padding in each result field) +*/ +#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) +#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) + + +/* 2-(4x32f) -> 4x32f UNPaCK High Packed Single-fp + (interleaves high half of dest with high half of source + as padding in each result field) +*/ +#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) +#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) + + + +/* Fp and mmX ReSTORe state +*/ +#ifdef SSE_TRACE + #define fxrstor(mem) \ + { \ + fprintf(stderr, "fxrstor()\n"); \ + __asm__ __volatile__ ("fxrstor %0" \ + : /* nothing */ \ + : "X" (mem)) \ + } +#else + #define fxrstor(mem) \ + __asm__ __volatile__ ("fxrstor %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif + + +/* Fp and mmX SAVE state +*/ +#ifdef SSE_TRACE + #define fxsave(mem) \ + { \ + fprintf(stderr, "fxsave()\n"); \ + __asm__ __volatile__ ("fxsave %0" \ + : /* nothing */ \ + : "X" (mem)) \ + } +#else + #define fxsave(mem) \ + __asm__ __volatile__ ("fxsave %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif + + +/* STore streaMing simd eXtensions Control/Status Register +*/ +#ifdef SSE_TRACE + #define stmxcsr(mem) \ + { \ + fprintf(stderr, "stmxcsr()\n"); \ + __asm__ __volatile__ ("stmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) \ + } +#else + #define stmxcsr(mem) \ + __asm__ __volatile__ ("stmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif + + +/* LoaD streaMing simd eXtensions Control/Status Register +*/ +#ifdef SSE_TRACE + #define ldmxcsr(mem) \ + { \ + fprintf(stderr, "ldmxcsr()\n"); \ + __asm__ __volatile__ ("ldmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) \ + } +#else + #define ldmxcsr(mem) \ + __asm__ __volatile__ ("ldmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif + + +/* Store FENCE - enforce ordering of stores before fence vs. stores + occuring after fence in source code. +*/ +#ifdef SSE_TRACE + #define sfence() \ + { \ + fprintf(stderr, "sfence()\n"); \ + __asm__ __volatile__ ("sfence\n\t") \ + } +#else + #define sfence() \ + __asm__ __volatile__ ("sfence\n\t") +#endif + + +/* PREFETCH data using T0, T1, T2, or NTA hint + T0 = Prefetch into all cache levels + T1 = Prefetch into all cache levels except 0th level + T2 = Prefetch into all cache levels except 0th and 1st levels + NTA = Prefetch data into non-temporal cache structure +*/ +#ifdef SSE_TRACE +#else + #define prefetch(mem, hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "X" (mem)) + + #define prefetcht0(mem) prefetch(mem, t0) + #define prefetcht1(mem) prefetch(mem, t1) + #define prefetcht2(mem) prefetch(mem, t2) + #define prefetchnta(mem) prefetch(mem, nta) +#endif + + + +#endif diff --git a/gst/deinterlace/tvtime/tomsmocomp.c b/gst/deinterlace/tvtime/tomsmocomp.c new file mode 100644 index 00000000..3141fbac --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp.c @@ -0,0 +1,211 @@ +/** + * Copyright (C) 2004 Billy Biggs + * Copyright (C) 2008 Sebastian Dröge + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "_stdint.h" +#include + +#include "gst/gst.h" +#include "gstdeinterlace.h" +#include "plugins.h" + +#define GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP)) +#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP)) +#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass)) +#define GST_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoComp)) +#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass)) +#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CAST(obj) ((GstDeinterlaceMethodTomsMoComp*)(obj)) + +GType gst_deinterlace_method_tomsmocomp_get_type (void); + +typedef struct +{ + GstDeinterlaceMethod parent; + + guint search_effort; + gboolean strange_bob; +} GstDeinterlaceMethodTomsMoComp; + +typedef struct +{ + GstDeinterlaceMethodClass parent_class; +} GstDeinterlaceMethodTomsMoCompClass; + +static int +Fieldcopy (void *dest, const void *src, size_t count, + int rows, int dst_pitch, int src_pitch) +{ + unsigned char *pDest = (unsigned char *) dest; + unsigned char *pSrc = (unsigned char *) src; + + int i; + + for (i = 0; i < rows; i++) { + oil_memcpy (pDest, pSrc, count); + pSrc += src_pitch; + pDest += dst_pitch; + } + return 0; +} + +#define USE_FOR_DSCALER + +#define IS_C +#define SIMD_TYPE C +#define FUNCT_NAME tomsmocompDScaler_C +#include "tomsmocomp/TomsMoCompAll.inc" +#undef IS_C +#undef SIMD_TYPE +#undef FUNCT_NAME + +#ifdef BUILD_X86_ASM + +#include "tomsmocomp/tomsmocompmacros.h" +#include "x86-64_macros.inc" + +#define IS_MMX +#define SIMD_TYPE MMX +#define FUNCT_NAME tomsmocompDScaler_MMX +#include "tomsmocomp/TomsMoCompAll.inc" +#undef IS_MMX +#undef SIMD_TYPE +#undef FUNCT_NAME + +#define IS_3DNOW +#define SIMD_TYPE 3DNOW +#define FUNCT_NAME tomsmocompDScaler_3DNOW +#include "tomsmocomp/TomsMoCompAll.inc" +#undef IS_3DNOW +#undef SIMD_TYPE +#undef FUNCT_NAME + +#define IS_MMXEXT +#define SIMD_TYPE MMXEXT +#define FUNCT_NAME tomsmocompDScaler_MMXEXT +#include "tomsmocomp/TomsMoCompAll.inc" +#undef IS_MMXEXT +#undef SIMD_TYPE +#undef FUNCT_NAME + +#endif + +G_DEFINE_TYPE (GstDeinterlaceMethodTomsMoComp, + gst_deinterlace_method_tomsmocomp, GST_TYPE_DEINTERLACE_METHOD); + +enum +{ + ARG_0, + ARG_SEARCH_EFFORT, + ARG_STRANGE_BOB +}; + +static void +gst_deinterlace_method_tomsmocomp_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeinterlaceMethodTomsMoComp *self = + GST_DEINTERLACE_METHOD_TOMSMOCOMP (object); + + switch (prop_id) { + case ARG_SEARCH_EFFORT: + self->search_effort = g_value_get_uint (value); + break; + case ARG_STRANGE_BOB: + self->strange_bob = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_deinterlace_method_tomsmocomp_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeinterlaceMethodTomsMoComp *self = + GST_DEINTERLACE_METHOD_TOMSMOCOMP (object); + + switch (prop_id) { + case ARG_SEARCH_EFFORT: + g_value_set_uint (value, self->search_effort); + break; + case ARG_STRANGE_BOB: + g_value_set_boolean (value, self->strange_bob); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void + gst_deinterlace_method_tomsmocomp_class_init + (GstDeinterlaceMethodTomsMoCompClass * klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; +#ifdef BUILD_X86_ASM + guint cpu_flags = oil_cpu_get_flags (); +#endif + + gobject_class->set_property = gst_deinterlace_method_tomsmocomp_set_property; + gobject_class->get_property = gst_deinterlace_method_tomsmocomp_get_property; + + g_object_class_install_property (gobject_class, ARG_SEARCH_EFFORT, + g_param_spec_uint ("search-effort", + "Search Effort", + "Search Effort", 0, 27, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + g_object_class_install_property (gobject_class, ARG_STRANGE_BOB, + g_param_spec_boolean ("strange-bob", + "Strange Bob", + "Use strange bob", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); + + dim_class->fields_required = 4; + dim_class->name = "Motion Adaptive: Motion Search"; + dim_class->nick = "tomsmocomp"; + dim_class->latency = 1; + +#ifdef BUILD_X86_ASM + if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { + dim_class->deinterlace_frame = tomsmocompDScaler_MMXEXT; + } else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) { + dim_class->deinterlace_frame = tomsmocompDScaler_3DNOW; + } else if (cpu_flags & OIL_IMPL_FLAG_MMX) { + dim_class->deinterlace_frame = tomsmocompDScaler_MMX; + } else { + dim_class->deinterlace_frame = tomsmocompDScaler_C; + } +#else + dim_class->deinterlace_frame = tomsmocompDScaler_C; +#endif +} + +static void +gst_deinterlace_method_tomsmocomp_init (GstDeinterlaceMethodTomsMoComp * self) +{ + self->search_effort = 5; + self->strange_bob = FALSE; +} diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoop0A.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoop0A.inc new file mode 100644 index 00000000..b1d9aeca --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoop0A.inc @@ -0,0 +1,15 @@ +// -*- c++ -*- + +// Searches just the center pixel, in both the old +// and new fields, but takes averages. This is an even +// pixel address. Any chroma match will be used. (YUY2) +// We best like finding 0 motion so we will bias everything we found previously +// up by a little, and adjust later + +#ifdef IS_SSE2 + "paddusb "_ONES", %%xmm7\n\t" // bias toward no motion +#else + "paddusb "_ONES", %%mm7\n\t" // bias toward no motion +#endif + + MERGE4PIXavg("(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")") // center, in old and new diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopBottom.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopBottom.inc new file mode 100644 index 00000000..e1560353 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopBottom.inc @@ -0,0 +1,174 @@ +// -*- c++ -*- + +// Version for non-SSE2 + +#ifndef IS_C + +#ifdef SKIP_SEARCH + "movq %%mm6, %%mm0\n\t" // just use the results of our wierd bob +#else + + + // JA 9/Dec/2002 + // failed experiment + // but leave in placeholder for me to play about +#ifdef DONT_USE_STRANGE_BOB + // Use the best weave if diffs less than 10 as that + // means the image is still or moving cleanly + // if there is motion we will clip which will catch anything + "psubusb "_FOURS", %%mm7\n\t" // sets bits to zero if weave diff < 4 + "pxor %%mm0, %%mm0\n\t" + "pcmpeqb %%mm0, %%mm7\n\t" // all ff where weave better, else 00 + "pcmpeqb %%mm7, %%mm0\n\t" // all ff where bob better, else 00 + "pand %%mm6, %%mm0\n\t" // use bob for these pixel values + "pand %%mm5, %%mm7\n\t" // use weave for these + "por %%mm7, %%mm0\n\t" // combine both +#else + // Use the better of bob or weave + // pminub mm4, TENS // the most we care about + V_PMINUB ("%%mm4", _TENS, "%%mm0") // the most we care about + + "psubusb %%mm4, %%mm7\n\t" // foregive that much from weave est? + "psubusb "_FOURS", %%mm7\n\t" // bias it a bit toward weave + "pxor %%mm0, %%mm0\n\t" + "pcmpeqb %%mm0, %%mm7\n\t" // all ff where weave better, else 00 + "pcmpeqb %%mm7, %%mm0\n\t" // all ff where bob better, else 00 + "pand %%mm6, %%mm0\n\t" // use bob for these pixel values + "pand %%mm5, %%mm7\n\t" // use weave for these + "por %%mm7, %%mm0\n\t" // combine both +#endif + + + // pminub mm0, Max_Vals // but clip to catch the stray error + V_PMINUB ("%%mm0", _Max_Vals, "%%mm1") // but clip to catch the stray error + // pmaxub mm0, Min_Vals + V_PMAXUB ("%%mm0", _Min_Vals) + +#endif + + + MOVX" "_pDest", %%"XAX"\n\t" + +#ifdef USE_VERTICAL_FILTER + "movq %%mm0, %%mm1\n\t" + // pavgb mm0, qword ptr["XBX"] + V_PAVGB ("%%mm0", "(%%"XBX")", "%%mm2", _ShiftMask) + // movntq qword ptr["XAX"+"XDX"], mm0 + V_MOVNTQ ("(%"XAX", %%"XDX")", "%%mm0") + // pavgb mm1, qword ptr["XBX"+"XCX"] + V_PAVGB ("%%mm1", "(%%"XBX", %%"XCX")", "%%mm2", _ShiftMask) + //FIXME: XDX or XAX!! + "addq "_dst_pitchw", %%"XBX + // movntq qword ptr["XAX"+"XDX"], mm1 + V_MOVNTQ ("(%%"XAX", %%"XDX")", "%%mm1") +#else + + // movntq qword ptr["XAX"+"XDX"], mm0 + V_MOVNTQ ("(%%"XAX", %%"XDX")", "%%mm0") +#endif + + LEAX" 8(%%"XDX"), %%"XDX"\n\t" // bump offset pointer + CMPX" "_Last8", %%"XDX"\n\t" // done with line? + "jb 1b\n\t" // y + + MOVX" "_oldbx", %%"XBX"\n\t" + + : /* no outputs */ + + : "m"(pBob), + "m"(src_pitch2), + "m"(ShiftMask), + "m"(pDest), + "m"(dst_pitchw), + "m"(Last8), + "m"(pSrc), + "m"(pSrcP), + "m"(pBobP), + "m"(DiffThres), + "m"(Min_Vals), + "m"(Max_Vals), + "m"(FOURS), + "m"(TENS), + "m"(ONES), + "m"(UVMask), + "m"(Max_Mov), + "m"(YMask), + "m"(oldbx) + + : XAX, XCX, XDX, XSI, XDI, + "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", +#ifdef __MMX__ + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", +#endif + "memory", "cc" + ); + + // adjust for next line + pSrc += src_pitch2; + pSrcP += src_pitch2; + pDest += dst_pitch2; + pBob += src_pitch2; + pBobP += src_pitch2; + } + + return 0; +#else +#ifdef SKIP_SEARCH + out[0] = best[0]; // just use the results of our wierd bob + out[1] = best[1]; +#else + diff[0] = diff[0] - MIN (diff[0], 10) - 4; + diff[1] = diff[1] - MIN (diff[1] - 10) - 4; + if (diff[0] < 0) + out[0] = weave[0]; + else + out[0] = best[0]; + + if (diff[1] < 0) + out[1] = weave[1]; + else + out[1] = best[1]; + + + out[0] = CLAMP (out[0], MinVals[0], MaxVals[0]); + out[1] = CLAMP (out[1], MinVals[1], MaxVals[1]); +#endif + +#ifdef USE_VERTICAL_FILTER + pDest[x] = (out[0] + pBob[0]) / 2; + pDest[x + dst_pitchw] = (pBob[src_pitch2] + out[0]) / 2; + pDest[x + 1] = (out[1] + pBob[1]) / 2; + pDest[x + 1 + dst_pitchw] = (pBob[src_pitch2 + 1] + out[1]) / 2; +#else + pDest[x] = out[0]; + pDest[x+1] = out[1]; +#endif + pBob += 2; + pBobP += 2; + pSrc += 2; + pSrcP += 2; + } + // adjust for next line + pSrc = src_pitch2 * (y+1) + pWeaveSrc; + pSrcP = src_pitch2 * (y+1) + pWeaveSrcP; + pDest = dst_pitch2 * (y+1) + pWeaveDest + dst_pitch2; + + + if (TopFirst) + { + pBob = pCopySrc + src_pitch2; + pBobP = pCopySrcP + src_pitch2; + } + else + { + pBob = pCopySrc; + pBobP = pCopySrcP; + } + + pBob += src_pitch2 * (y+1); + pBobP += src_pitch2 * (y+1); + } + + return 0; + +#endif diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA.inc new file mode 100644 index 00000000..6208fe8c --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA.inc @@ -0,0 +1,11 @@ +// -*- c++ -*- + +// Searches 2 pixel to the left and right, in both the old +// and new fields, but takes averages. These are even +// pixel addresses. Chroma match will be used. (YUY2) + MERGE4PIXavg("-4(%%"XDI")", "4(%%"XSI", %%"XCX", 2)") // up left, down right + MERGE4PIXavg("4(%%"XDI")", "-4(%%"XSI", %%"XCX", 2)") // up right, down left + MERGE4PIXavg("-4(%%"XDI", %%"XCX")", "4(%%"XSI", %%"XCX")") // left, right + MERGE4PIXavg("4(%%"XDI", %%"XCX")", "-4(%%"XSI", %%"XCX")") // right, left + MERGE4PIXavg("-4(%%"XDI", %%"XCX", 2)", "4(%%"XSI")") // down left, up right + MERGE4PIXavg("4(%%"XDI", %%"XCX", 2)", "-4(%%"XSI")") // down right, up left diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA8.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA8.inc new file mode 100644 index 00000000..2841c3f6 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopEdgeA8.inc @@ -0,0 +1,12 @@ +// -*- c++ -*- + +// Searches 4 pixel to the left and right, in both the old +// and new fields, but takes averages. These are even +// pixel addresses. Chroma match will be used. (YUY2) + MERGE4PIXavg("-8(%%"XDI")", "8(%%"XSI", %%"XCX", 2)") // up left, down right + MERGE4PIXavg("8(%%"XDI")", "-8(%%"XSI", %%"XCX", 2)") // up right, down left + MERGE4PIXavg("-8(%%"XDI", %%"XCX")", "8(%%"XSI", %%"XCX")") // left, right + MERGE4PIXavg("8(%%"XDI", %%"XCX")", "-8(%%"XSI", %%"XCX")") // right, left + MERGE4PIXavg("-8(%%"XDI", %%"XCX", 2)", "8(%%"XSI")") // down left, up right + MERGE4PIXavg("8(%%"XDI", %%"XCX", 2)", "-8(%%"XSI")") // down right, up left + diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA.inc new file mode 100644 index 00000000..ab5375f4 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA.inc @@ -0,0 +1,10 @@ +// -*- c++ -*- + +// Searches 1 pixel to the left and right, in both the old +// and new fields, but takes averages. These are odd +// pixel addresses. Any chroma match will not be used. (YUY2) + MERGE4PIXavg("-2(%%"XDI")", "2(%%"XSI", %%"XCX", 2)") // up left, down right + MERGE4PIXavg("2(%%"XDI")", "-2(%%"XSI", %%"XCX", 2)") // up right, down left + MERGE4PIXavg("-2(%%"XDI", %%"XCX", 2)", "2(%%"XSI")") // down left, up right + MERGE4PIXavg("2(%%"XDI", %%"XCX", 2)", "-2(%%"XSI")") // down right, up left +#include "SearchLoopOddA2.inc" diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA2.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA2.inc new file mode 100644 index 00000000..fd3f6fb0 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA2.inc @@ -0,0 +1,5 @@ +// Searches 1 pixel to the left and right, in both the old +// and new fields, but takes averages. These are odd +// pixel addresses. Any chroma match will not be used. (YUY2) + MERGE4PIXavg("-2(%%"XDI", %%"XCX")", "2(%%"XSI", %%"XCX")") // left, right + MERGE4PIXavg("2(%%"XDI", %%"XCX")", "-2(%%"XSI", %%"XCX")") // right, left diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA6.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA6.inc new file mode 100644 index 00000000..cbae014e --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddA6.inc @@ -0,0 +1,11 @@ +// -*- c++ -*- + +// Searches 3 pixels to the left and right, in both the old +// and new fields, but takes averages. These are odd +// pixel addresses. Any chroma match will not be used. (YUY2) + MERGE4PIXavg("-6(%%"XDI")", "6(%%"XSI", %%"XCX", 2)") // up left, down right + MERGE4PIXavg("6(%%"XDI")", "-6(%%"XSI", %%"XCX", 2)") // up right, down left + MERGE4PIXavg("-6(%%"XDI", %%"XCX")", "6(%%"XSI", %%"XCX")") // left, right + MERGE4PIXavg("6(%%"XDI", %%"XCX")", "-6(%%"XSI", %%"XCX")") // right, left + MERGE4PIXavg("-6(%%"XDI", %%"XCX", 2)", "6(%%"XSI")") // down left, up right + MERGE4PIXavg("6(%%"XDI", %%"XCX", 2)", "-6(%%"XSI")") // down right, up left diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH.inc new file mode 100644 index 00000000..e59e3c7e --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH.inc @@ -0,0 +1,10 @@ +// Searches 1 pixel to the left and right, in both the old +// and new fields, but takes v-half pel averages. These are odd +// pixel addresses. Any chroma match will not be used. (YUY2) + __asm + { + MERGE4PIXavgH("XDI"-2, "XDI"+"XCX"-2, "XSI"+"XCX"+2, "XSI"+2*"XCX"+2) // up left, down right + MERGE4PIXavgH("XDI"+2, "XDI"+"XCX"+2, "XSI"+"XCX"-2, "XSI"+2*"XCX"-2) // up right, down left + MERGE4PIXavgH("XDI"+2*"XCX"-2, "XDI"+"XCX"-2, "XSI"+"XCX"+2, "XSI"+2) // down left, up right + MERGE4PIXavgH("XDI"+2*"XCX"+2, "XDI"+"XCX"+2, "XSI"+"XCX"-2, "XSI"-2) // down right, up left + } diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH2.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH2.inc new file mode 100644 index 00000000..cd7d812a --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopOddAH2.inc @@ -0,0 +1,5 @@ +// Searches 1 pixel to the left and right, in both the old +// and new fields, but takes vertical averages. These are odd +// pixel addresses. Any chroma match will not be used. (YUY2) + MERGE4PIXavgH("-2(%%"XDI", %%"XCX")", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "2(%%"XSI", %%"XCX")") // left, right + MERGE4PIXavgH("2(%%"XDI", %%"XCX")", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "-2(%%"XSI", %%"XCX")") // right, left diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc new file mode 100644 index 00000000..9d6a490f --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopTop.inc @@ -0,0 +1,254 @@ +// -*- c++ -*- + +unsigned char* pDest; +const unsigned char* pSrcP; +const unsigned char* pSrc; +const unsigned char* pBob; +const unsigned char* pBobP; + +// long is int32 on ARCH_368, int64 on ARCH_AMD64. Declaring it this way +// saves a lot of xor's to delete 64bit garbage. + +#if defined(DBL_RESIZE) || defined(USE_FOR_DSCALER) +long src_pitch2 = src_pitch; // even & odd lines are not interleaved in DScaler +#else +long src_pitch2 = 2 * src_pitch; // even & odd lines are interleaved in Avisynth +#endif + + +long dst_pitch2 = 2 * dst_pitch; +long y; + +long Last8; + + pSrc = pWeaveSrc; // points 1 weave line above + pSrcP = pWeaveSrcP; // " + +#ifdef DBL_RESIZE + +#ifdef USE_VERTICAL_FILTER + pDest = pWeaveDest + dst_pitch2; +#else + pDest = pWeaveDest + 3*dst_pitch; +#endif + +#else + +#ifdef USE_VERTICAL_FILTER + pDest = pWeaveDest + dst_pitch; +#else + pDest = pWeaveDest + dst_pitch2; +#endif + +#endif + + if (TopFirst) + { + pBob = pCopySrc + src_pitch2; // remember one weave line just copied previously + pBobP = pCopySrcP + src_pitch2; + } + else + { + pBob = pCopySrc; + pBobP = pCopySrcP; + } + +#ifndef IS_C + +#ifndef _pBob +#define _pBob "%0" +#define _src_pitch2 "%1" +#define _ShiftMask "%2" +#define _pDest "%3" +#define _dst_pitchw "%4" +#define _Last8 "%5" +#define _pSrc "%6" +#define _pSrcP "%7" +#define _pBobP "%8" +#define _DiffThres "%9" +#define _Min_Vals "%10" +#define _Max_Vals "%11" +#define _FOURS "%12" +#define _TENS "%13" +#define _ONES "%14" +#define _UVMask "%15" +#define _Max_Mov "%16" +#define _YMask "%17" +#define _oldbx "%18" +#endif + Last8 = (rowsize-8); + + for (y=1; y < FldHeight-1; y++) + { + long dst_pitchw = dst_pitch; // local stor so asm can ref + int64_t Max_Mov = 0x0404040404040404ull; + int64_t DiffThres = 0x0f0f0f0f0f0f0f0full; + int64_t YMask = 0x00ff00ff00ff00ffull; // keeps only luma + int64_t UVMask = 0xff00ff00ff00ff00ull; // keeps only chroma + int64_t TENS = 0x0a0a0a0a0a0a0a0aull; + int64_t FOURS = 0x0404040404040404ull; + int64_t ONES = 0x0101010101010101ull; + int64_t Min_Vals = 0x0000000000000000ull; + int64_t Max_Vals = 0x0000000000000000ull; + int64_t ShiftMask = 0xfefffefffefffeffull; + + long oldbx; + + // pretend it's indented -->> + __asm__ __volatile__ + ( + // Loop general reg usage + // + // XAX - pBobP, then pDest + // XBX - pBob + // XCX - src_pitch2 + // XDX - current offset + // XDI - prev weave pixels, 1 line up + // XSI - next weave pixels, 1 line up + + // Save "XBX" (-fPIC) + MOVX" %%"XBX", "_oldbx"\n\t" + + // simple bob first 8 bytes + MOVX" "_pBob", %%"XBX"\n\t" + MOVX" "_src_pitch2", %%"XCX"\n\t" + +#ifdef USE_VERTICAL_FILTER + "movq (%%"XBX"), %%mm0\n\t" + "movq (%%"XBX", %%"XCX"), %%mm1\n\t" //, qword ptr["XBX"+"XCX"] + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // halfway between + V_PAVGB ("%%mm0", "%%mm2", "%%mm3", _ShiftMask) // 1/4 way + V_PAVGB ("%%mm1", "%%mm2", "%%mm3", _ShiftMask) // 3/4 way + MOVX" "_pDest", %%"XDI"\n\t" + MOVX" "_dst_pitchw", %%"XAX"\n\t" + V_MOVNTQ ("(%%"XDI")", "%%mm0") + V_MOVNTQ ("(%%"XDI", %%"XAX")", "%%mm1") // qword ptr["XDI"+"XAX"], mm1 + + // simple bob last 8 bytes + MOVX" "_Last8", %%"XDX"\n\t" + LEAX" (%%"XBX", %%"XDX"), %%"XSI"\n\t" // ["XBX"+"XDX"] + "movq (%%"XSI"), %%mm0\n\t" + "movq (%%"XSI", %%"XCX"), %%mm1\n\t" // qword ptr["XSI"+"XCX"] + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // halfway between + V_PAVGB ("%%mm0", "%%mm2", "%%mm3", _ShiftMask) // 1/4 way + V_PAVGB ("%%mm1", "%%mm2", "%%mm3", _ShiftMask) // 3/4 way + ADDX" %%"XDX", %%"XDI"\n\t" // last 8 bytes of dest + V_MOVNTQ ("%%"XDI"", "%%mm0") + V_MOVNTQ ("(%%"XDI", %%"XAX")", "%%mm1") // qword ptr["XDI"+"XAX"], mm1) + +#else + "movq (%%"XBX"), %%mm0\n\t" + // pavgb mm0, qword ptr["XBX"+"XCX"] + V_PAVGB ("%%mm0", "(%%"XBX", %%"XCX")", "%%mm2", _ShiftMask) // qword ptr["XBX"+"XCX"], mm2, ShiftMask) + MOVX" "_pDest", %%"XDI"\n\t" + V_MOVNTQ ("(%%"XDI")", "%%mm0") + + // simple bob last 8 bytes + MOVX" "_Last8", %%"XDX"\n\t" + LEAX" (%%"XBX", %%"XDX"), %%"XSI"\n\t" //"XSI", ["XBX"+"XDX"] + "movq (%%"XSI"), %%mm0\n\t" + // pavgb mm0, qword ptr["XSI"+"XCX"] + V_PAVGB ("%%mm0", "(%%"XSI", %%"XCX")", "%%mm2", _ShiftMask) // qword ptr["XSI"+"XCX"], mm2, ShiftMask) + V_MOVNTQ ("(%%"XDI", %%"XDX")", "%%mm0") // qword ptr["XDI"+"XDX"], mm0) +#endif + // now loop and get the middle qwords + MOVX" "_pSrc", %%"XSI"\n\t" + MOVX" "_pSrcP", %%"XDI"\n\t" + MOVX" $8, %%"XDX"\n\t" // curr offset longo all lines + + "1:\n\t" + MOVX" "_pBobP", %%"XAX"\n\t" + ADDX" $8, %%"XDI"\n\t" + ADDX" $8, %%"XSI"\n\t" + ADDX" $8, %%"XBX"\n\t" + ADDX" %%"XDX", %%"XAX"\n\t" + +#ifdef USE_STRANGE_BOB +#include "StrangeBob.inc" +#else +#include "WierdBob.inc" +#endif + + // For non-SSE2: + // through out most of the rest of this loop we will maintain + // mm4 our min bob value + // mm5 best weave pixels so far + // mm6 our max Bob value + // mm7 best weighted pixel ratings so far + + // We will keep a slight bias to using the weave pixels + // from the current location, by rating them by the min distance + // from the Bob value instead of the avg distance from that value. + // our best and only rating so far + "pcmpeqb %%mm7, %%mm7\n\t" // ffff, say we didn't find anything good yet + +#else + Last8 = (rowsize - 4); + + for (y=1; y < FldHeight-1; y++) + { + #ifdef USE_STRANGE_BOB + long DiffThres = 0x0f; + #endif + + #ifndef SKIP_SEARCH + long weave[2], MaxVals[2], MinVals[2]; + #endif + + long diff[2], best[2], avg[2], diff2[2], out[2], x; + +#ifdef USE_VERTICAL_FILTER + pDest[0] = (3 * pBob[0] + pBob[src_pitch2]) / 4; + pDest[1] = (3 * pBob[1] + pBob[src_pitch2 + 1]) / 4; + pDest[2] = (3 * pBob[2] + pBob[src_pitch2 + 2]) / 4; + pDest[3] = (3 * pBob[3] + pBob[src_pitch2 + 3]) / 4; + pDest[dst_pitchw] = (pBob[0] + 3 * pBob[src_pitch2]) / 4; + pDest[dst_pitchw + 1] = (pBob[1] + 3 * pBob[src_pitch2 + 1]) / 4; + pDest[dst_pitchw + 2] = (pBob[2] + 3 * pBob[src_pitch2 + 2]) / 4; + pDest[dst_pitchw + 3] = (pBob[3] + 3 * pBob[src_pitch2 + 3]) / 4; + + // simple bob last byte + pDest[Last8] = (3 * pBob[Last8] + pBob[Last8 + src_pitch2]) / 4; + pDest[Last8 + 1] = (3 * pBob[Last8 + 1] + pBob[Last8 + src_pitch2 + 1]) / 4; + pDest[Last8 + 2] = (3 * pBob[Last8 + 2] + pBob[Last8 + src_pitch2 + 2]) / 4; + pDest[Last8 + 3] = (3 * pBob[Last8 + 3] + pBob[Last8 + src_pitch2 + 3]) / 4; + pDest[Last8 + src_pitch2] = (pBob[Last8] + 3 * pBob[Last8 + src_pitch2]) / 4; + pDest[Last8 + src_pitch2 + 1] = (pBob[Last8 + 1] + 3 * pBob[Last8 + src_pitch2 + 1]) / 4; + pDest[Last8 + src_pitch2 + 2] = (pBob[Last8 + 2] + 3 * pBob[Last8 + src_pitch2 + 2]) / 4; + pDest[Last8 + src_pitch2 + 3] = (pBob[Last8 + 3] + 3 * pBob[Last8 + src_pitch2 + 3]) / 4; +#else + pDest[0] = (pBob[0] + pBob[src_pitch2 + 1]) / 2; + pDest[1] = (pBob[1] + pBob[src_pitch2 + 1]) / 2; + pDest[2] = (pBob[2] + pBob[src_pitch2 + 2]) / 2; + pDest[3] = (pBob[3] + pBob[src_pitch2 + 3]) / 2; + + // simple bob last byte + pDest[Last8] = (pBob[Last8] + pBob[Last8 + src_pitch2]) / 2; + pDest[Last8 + 1] = (pBob[Last8 + 1] + pBob[Last8 + src_pitch2 + 1]) / 2; + pDest[Last8 + 2] = (pBob[Last8 + 2] + pBob[Last8 + src_pitch2 + 2]) / 2; + pDest[Last8 + 3] = (pBob[Last8 + 3] + pBob[Last8 + src_pitch2 + 3]) / 2; +#endif + + pBob += 4; + pBobP += 4; + pSrc += 4; + pSrcP += 4; + + for (x=4; x < Last8; x += 2) { + +#ifdef USE_STRANGE_BOB +#include "StrangeBob.inc" +#else +#include "WierdBob.inc" +#endif + + // We will keep a slight bias to using the weave pixels + // from the current location, by rating them by the min distance + // from the Bob value instead of the avg distance from that value. + // our best and only rating so far + diff[0] = diff[1] = 255; + + +#endif diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopVA.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopVA.inc new file mode 100644 index 00000000..3e3d19b5 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopVA.inc @@ -0,0 +1,6 @@ +// -*- c++ -*- + +// Searches the center vertical line above center and below, in both the old +// and new fields, but takes averages. These are even pixel addresses. + MERGE4PIXavg("(%%"XDI", %%"XCX", 2)", "(%%"XSI")") // down, up + MERGE4PIXavg("(%%"XDI")", "(%%"XSI", %%"XCX", 2)") // up, down diff --git a/gst/deinterlace/tvtime/tomsmocomp/SearchLoopVAH.inc b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopVAH.inc new file mode 100644 index 00000000..33155bc1 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/SearchLoopVAH.inc @@ -0,0 +1,6 @@ +// -*- c++ -*- + +// Searches the center vertical line above center and below, in both the old +// and new fields, but takes averages. These are even pixel addresses. + MERGE4PIXavgH("(%%"XDI", %%"XCX", 2)", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "(%%"XSI")") // down, up + MERGE4PIXavgH("(%%"XDI")", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "(%%"XSI", %%"XCX", 2)") // up, down diff --git a/gst/deinterlace/tvtime/tomsmocomp/StrangeBob.inc b/gst/deinterlace/tvtime/tomsmocomp/StrangeBob.inc new file mode 100644 index 00000000..45b4c865 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/StrangeBob.inc @@ -0,0 +1,435 @@ +// -*- c++ -*- + + // First, get and save our possible Bob values + // Assume our pixels are layed out as follows with x the calc'd bob value + // and the other pixels are from the current field + // + // j a b c k current field + // x calculated line + // m d e f n current field + // + // we calc the bob value luma value as: + // if |j - n| < Thres && |a - m| > Thres + // avg(j,n) + // end if + // if |k - m| < Thres && |c - n| > Thres + // avg(k,m) + // end if + // if |c - d| < Thres && |b - f| > Thres + // avg(c,d) + // end if + // if |a - f| < Thres && |b - d| > Thres + // avg(a,f) + // end if + // if |b - e| < Thres + // avg(b,e) + // end if + // pickup any thing not yet set with avg(b,e) + +#ifndef IS_C + + // j, n + "pxor %%mm5, %%mm5\n\t" + "pxor %%mm6, %%mm6\n\t" + "pxor %%mm7, %%mm7\n\t" + + "movq -2(%%"XBX"), %%mm0\n\t" // value a from top left + "movq -4(%%"XBX", %%"XCX"), %%mm1\n\t" // value m from bottom right + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(a,m) + + "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(a,m) > Thres else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(a,m) < Thres, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(a,m) > Thres, else 00 + + + "movq -4(%%"XBX"), %%mm0\n\t" // value j + "movq 4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(j,n) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm0\n\t" + "psubusb %%mm3, %%mm1\n\t" + "por %%mm1, %%mm0\n\t" // abs(j,n) + + "movq %%mm0, %%mm1\n\t" + "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(j,n) > Thres else 0 + "pxor %%mm3, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(j,n) < Thres, else 00 + + "pand %%mm4, %%mm1\n\t" + "pand %%mm1, %%mm2\n\t" + "pand %%mm1, %%mm0\n\t" + + "movq %%mm1, %%mm3\n\t" + "pxor %%mm5, %%mm3\n\t" + "pand %%mm3, %%mm6\n\t" + "pand %%mm3, %%mm7\n\t" + "pand %%mm3, %%mm5\n\t" + + "por %%mm1, %%mm5\n\t" + "por %%mm2, %%mm6\n\t" + "por %%mm0, %%mm7\n\t" + + // k & m + "movq 2(%%"XBX"), %%mm0\n\t" // value c from top left + "movq 4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n from bottom right + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(c,n) + + "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(c,n) > Thres else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(c,n) < Thres, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(c,n) > Thres, else 00 + + + "movq 4(%%"XBX"), %%mm0\n\t" // value k + "movq -4(%%"XBX", %%"XCX"), %%mm1\n\t" // value m + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(k,m) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm0\n\t" + "psubusb %%mm3, %%mm1\n\t" + "por %%mm1, %%mm0\n\t" // abs(k,m) + + "movq %%mm0, %%mm1\n\t" + "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(k,m) > Thres else 0 + "pxor %%mm3, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(k,m) < Thres, else 00 + + "pand %%mm4, %%mm1\n\t" + + "pand %%mm1, %%mm2\n\t" + "pand %%mm1, %%mm0\n\t" + + "movq %%mm1, %%mm3\n\t" + "pxor %%mm5, %%mm3\n\t" + "pand %%mm3, %%mm6\n\t" + "pand %%mm3, %%mm7\n\t" + "pand %%mm3, %%mm5\n\t" + + "por %%mm1, %%mm5\n\t" + "por %%mm2, %%mm6\n\t" + "por %%mm0, %%mm7\n\t" + + + // c & d + "movq (%%"XBX"), %%mm0\n\t" // value b from top left + "movq 2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f from bottom right + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(b,f) + + "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(b,f) > Thres else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(b,f) < Thres, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(b,f) > Thres, else 00 + + "movq 2(%%"XBX"), %%mm0\n\t" // value c + "movq -2(%%"XBX", %%"XCX"), %%mm1\n\t" // value d + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(c,d) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm0\n\t" + "psubusb %%mm3, %%mm1\n\t" + "por %%mm1, %%mm0\n\t" // abs(c,d) + + "movq %%mm0, %%mm1\n\t" + "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(c,d) > Thres else 0 + "pxor %%mm3, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(c,d) < Thres, else 00 + + "pand %%mm4, %%mm1\n\t" + + "pand %%mm1, %%mm2\n\t" + "pand %%mm1, %%mm0\n\t" + + "movq %%mm1, %%mm3\n\t" + "pxor %%mm5, %%mm3\n\t" + "pand %%mm3, %%mm6\n\t" + "pand %%mm3, %%mm7\n\t" + "pand %%mm3, %%mm5\n\t" + + "por %%mm1, %%mm5\n\t" + "por %%mm2, %%mm6\n\t" + "por %%mm0, %%mm7\n\t" + + // a & f + "movq (%%"XBX"), %%mm0\n\t" // value b from top left + "movq -2(%%"XBX", %%"XCX"), %%mm1\n\t" // value d from bottom right + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(b,d) + + "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(b,d) > Thres else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(b,d) < Thres, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(b,d) > Thres, else 00 + + "movq -2(%%"XBX"), %%mm0\n\t" // value a + "movq 2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(a,f) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm0\n\t" + "psubusb %%mm3, %%mm1\n\t" + "por %%mm1, %%mm0\n\t" // abs(a,f) + + "movq %%mm0, %%mm1\n\t" + "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(a,f) > Thres else 0 + "pxor %%mm3, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(a,f) < Thres, else 00 + + "pand %%mm4, %%mm1\n\t" + + "pand %%mm1, %%mm2\n\t" + "pand %%mm1, %%mm0\n\t" + + "movq %%mm1, %%mm3\n\t" + "pxor %%mm5, %%mm3\n\t" + "pand %%mm3, %%mm6\n\t" + "pand %%mm3, %%mm7\n\t" + "pand %%mm3, %%mm5\n\t" + + "por %%mm1, %%mm5\n\t" + "por %%mm2, %%mm6\n\t" + "por %%mm0, %%mm7\n\t" + + "pand "_YMask", %%mm5\n\t" // mask out chroma from here + "pand "_YMask", %%mm6\n\t" // mask out chroma from here + "pand "_YMask", %%mm7\n\t" // mask out chroma from here + + // b,e + "movq (%%"XBX"), %%mm0\n\t" // value b from top + "movq (%%"XBX", %%"XCX"), %%mm1\n\t" // value e from bottom + "movq %%mm0, %%mm2\n\t" + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(b,e) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm0\n\t" + "psubusb %%mm3, %%mm1\n\t" + "por %%mm1, %%mm0\n\t" // abs(b,e) + + "movq %%mm0, %%mm1\n\t" + "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(b,e) > Thres else 0 + "pxor %%mm3, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(b,e) < Thres, else 00 + + "pand %%mm1, %%mm2\n\t" + "pand %%mm1, %%mm0\n\t" + + "movq %%mm1, %%mm3\n\t" + "pxor %%mm5, %%mm3\n\t" + "pand %%mm3, %%mm6\n\t" + "pand %%mm3, %%mm7\n\t" + "pand %%mm3, %%mm5\n\t" + + "por %%mm1, %%mm5\n\t" + "por %%mm2, %%mm6\n\t" + "por %%mm0, %%mm7\n\t" + + // bob in any leftovers + "movq (%%"XBX"), %%mm0\n\t" // value b from top + "movq (%%"XBX", %%"XCX"), %%mm1\n\t" // value e from bottom + + +// We will also calc here the max/min values to later limit comb +// so the max excursion will not exceed the Max_Comb constant + +#ifdef SKIP_SEARCH + "movq %%mm0, %%mm2\n\t" +// pminub %%mm2, %%mm1 + V_PMINUB ("%%mm2", "%%mm1", "%%mm4") + +// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this + V_PMAXUB ("%%mm6", "%%mm2") + "movq %%mm0, %%mm2\n\t" + V_PMAXUB ("%%mm2", "%%mm1") +// pminub %%mm6, %%mm2 // clip our current results so far to be below this + V_PMINUB ("%%mm6", "%%mm2", "%%mm4") + +#else + "movq %%mm0, %%mm2\n\t" + "movq (%%"XAX"), %%mm4\n\t" + "psubusb %%mm4, %%mm2\n\t" + "psubusb %%mm0, %%mm4\n\t" + "por %%mm2, %%mm4\n\t" // abs diff + + "movq %%mm1, %%mm2\n\t" + "movq (%%"XAX", %%"XCX"), %%mm3\n\t" + "psubusb %%mm3, %%mm2\n\t" + "psubusb %%mm1, %%mm3\n\t" + "por %%mm2, %%mm3\n\t" // abs diff +// pmaxub %%mm3, %%mm4 // top or bottom pixel moved most + V_PMAXUB ("%%mm3", "%%mm4") // top or bottom pixel moved most + "psubusb "_DiffThres", %%mm3\n\t" // moved more than allowed? or goes to 0? + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where low motion, else high motion + + "movq %%mm0, %%mm2\n\t" +// pminub %%mm2, %%mm1 + V_PMINUB ("%%mm2", "%%mm1", "%%mm4") + +// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this + V_PMAXUB ("%%mm6", "%%mm2") + + "psubusb %%mm3, %%mm2\n\t" // maybe decrease it to 0000.. if no surround motion + "movq %%mm2, "_Min_Vals"\n\t" + + "movq %%mm0, %%mm2\n\t" + V_PMAXUB ("%%mm2", "%%mm1") +// pminub %%mm6, %%mm2 // clip our current results so far to be below this + V_PMINUB ("%%mm6", "%%mm2", "%%mm4") + "paddusb %%mm3, %%mm2\n\t" // maybe increase it to ffffff if no surround motion + "movq %%mm2, "_Max_Vals"\n\t" +#endif + + "movq %%mm0, %%mm2\n\t" +// pavgb %%mm2, %%mm1 // avg(b,e) + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(b,e) + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(b,e) + "movq %%mm3, %%mm1\n\t" // keep copy of diffs + + "pxor %%mm4, %%mm4\n\t" + "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 + "pcmpeqb %%mm0, %%mm0\n\t" + "pandn %%mm0, %%mm5\n\t" + "por %%mm5, %%mm3\n\t" + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 + + "pand %%mm3, %%mm1\n\t" + "pand %%mm3, %%mm2\n\t" + + "pand %%mm4, %%mm6\n\t" + "pand %%mm4, %%mm7\n\t" + + "por %%mm2, %%mm6\n\t" // our x2 value + "por %%mm1, %%mm7\n\t" // our x2 diffs + "movq %%mm7, %%mm4\n\t" // save as bob uncertainty indicator + +#else + + diff[0] = -1; + diff[1] = -1; + best[0] = 0; + best[1] = 0; + // j, n + if (ABS (pBob[-2] - pBob[src_pitch2 - 4]) < DiffThres && + ABS (pBob[-4] - pBob[src_pitch2 + 4]) > DiffThres) { + best[0] = (pBob[-2] + pBob[src_pitch2 - 4]) / 2; + diff[0] = ABS (pBob[-2] - pBob[src_pitch2 - 4]); + } + if (ABS (pBob[-1] - pBob[src_pitch2 - 3]) < DiffThres && + ABS (pBob[-3] - pBob[src_pitch2 + 5]) > DiffThres) { + best[1] = (pBob[-1] + pBob[src_pitch2 - 3]) / 2; + diff[1] = ABS (pBob[-1] - pBob[src_pitch2 - 3]); + } + + // k & m + if (ABS (pBob[2] - pBob[src_pitch2 + 4]) < DiffThres && + ABS (pBob[4] - pBob[src_pitch2 - 4]) > DiffThres) { + best[0] = (pBob[4] + pBob[src_pitch2 - 4]) / 2; + diff[0] = ABS (pBob[4] - pBob[src_pitch2 - 4]); + } + + if (ABS (pBob[3] - pBob[src_pitch2 + 5]) < DiffThres && + ABS (pBob[5] - pBob[src_pitch2 - 3]) > DiffThres) { + best[1] = (pBob[5] + pBob[src_pitch2 - 3]) / 2; + diff[1] = ABS (pBob[5] - pBob[src_pitch2 - 3]); + } + + // c & d + if (ABS (pBob[0] - pBob[src_pitch2 + 2]) < DiffThres && + ABS (pBob[2] - pBob[src_pitch2 - 2]) > DiffThres) { + best[0] = (pBob[2] + pBob[src_pitch2 - 2]) / 2; + diff[0] = ABS (pBob[2] - pBob[src_pitch2 - 2]); + } + + if (ABS (pBob[1] - pBob[src_pitch2 + 3]) < DiffThres && + ABS (pBob[3] - pBob[src_pitch2 - 1]) > DiffThres) { + best[1] = (pBob[3] + pBob[src_pitch2 - 1]) / 2; + diff[1] = ABS (pBob[3] - pBob[src_pitch2 - 1]); + } + + // a & f + if (ABS (pBob[0] - pBob[src_pitch2 - 2]) < DiffThres && + ABS (pBob[-2] - pBob[src_pitch2 + 2]) > DiffThres) { + best[0] = (pBob[-2] + pBob[src_pitch2 + 2]) / 2; + diff[0] = ABS (pBob[-2] - pBob[src_pitch2 + 2]); + } + + if (ABS (pBob[1] - pBob[src_pitch2 - 1]) < DiffThres && + ABS (pBob[-1] - pBob[src_pitch2 + 3]) > DiffThres) { + best[1] = (pBob[-1] + pBob[src_pitch2 + 3]) / 2; + diff[1] = ABS (pBob[-1] - pBob[src_pitch2 + 3]); + } + + // b,e + if (ABS (pBob[0] - pBob[src_pitch2]) < DiffThres) { + best[0] = (pBob[0] + pBob[src_pitch2]) / 2; + diff[0] = ABS (pBob[0] - pBob[src_pitch2]); + } + + if (ABS (pBob[1] - pBob[src_pitch2 + 1]) < DiffThres) { + best[1] = (pBob[1] + pBob[src_pitch2 + 1]) / 2; + diff[1] = ABS (pBob[1] - pBob[src_pitch2 + 1]); + } + + +// We will also calc here the max/min values to later limit comb +// so the max excursion will not exceed the Max_Comb constant + +#ifdef SKIP_SEARCH + best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); + best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); +#else + mov[0] = MAX (ABS (pBob[0] - pBobP[0]), ABS (pBob[src_pitch2] - pBobP[src_pitch2])); + mov[1] = MAX (ABS (pBob[1] - pBobP[1]), ABS (pBob[src_pitch2 + 1] - pBobP[src_pitch2 + 1])); + + MinVals[0] = 0; + MinVals[1] = 0; + MaxVals[0] = 255; + MaxVals[1] = 255; + if (mov[0] > DiffThres) { + MinVals[0] = MAX (MIN (pBob[0], pBob[src_pitch2]), best[0]); + MaxVals[0] = MIN (MAX (pBob[0], pBob[src_pitch2]), best[0]); + } + + if (mov[1] > DiffThres) { + MinVals[1] = MAX (MIN (pBob[1], pBob[src_pitch2+1]), best[1]); + MaxVals[1] = MIN (MAX (pBob[1], pBob[src_pitch2+1]), best[1]); + } + + best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); + best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); +#endif + avg[0] = (pBob[src_pitch2] + pBob[0]) / 2; + avg[1] = (pBob[src_pitch2 + 1] + pBob[1]) / 2; + diff2[0] = ABS (pBob[src_pitch2 + 1] - pBob[1]); + diff2[1] = ABS (pBob[src_pitch2 + 1] - pBob[1]); + + if (diff[0] == -1 || diff2[0] < diff[0]) { + best[0] = avg[0]; + diff[0] = diff2[0]; + } + + if (diff[1] == -1 || diff2[1] < diff[1]) { + best[1] = avg[1]; + diff[1] = diff2[1]; + } +#endif diff --git a/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc b/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc new file mode 100644 index 00000000..e8883dd3 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll.inc @@ -0,0 +1,241 @@ +/* + * GStreamer + * Copyright (c) 2002 Tom Barry All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Relicensed for GStreamer from GPL to LGPL with permit from Tom Barry. + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + + +#ifndef TopFirst +#define TopFirst IsOdd +#endif + +#ifdef SEFUNC +#undef SEFUNC +#endif + +#if defined(IS_MMXEXT) +#define SEFUNC(x) Search_Effort_MMXEXT_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) +#elif defined(IS_3DNOW) +#define SEFUNC(x) Search_Effort_3DNOW_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) +#elif defined(IS_MMX) +#define SEFUNC(x) Search_Effort_MMX_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) +#else +#define SEFUNC(x) Search_Effort_C_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) +#endif + +#include "TomsMoCompAll2.inc" + +#define USE_STRANGE_BOB + +#include "TomsMoCompAll2.inc" + +#undef USE_STRANGE_BOB + +#undef SEFUNC +#if defined(IS_MMXEXT) +#define SEFUNC(x) Search_Effort_MMXEXT_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) +#elif defined(IS_3DNOW) +#define SEFUNC(x) Search_Effort_3DNOW_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) +#elif defined(IS_MMX) +#define SEFUNC(x) Search_Effort_MMX_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) +#else +#define SEFUNC(x) Search_Effort_C_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) +#endif + +void FUNCT_NAME(GstDeinterlaceMethod *d_method, GstDeinterlace* object, GstBuffer *outbuf) +{ + GstDeinterlaceMethodTomsMoComp *self = GST_DEINTERLACE_METHOD_TOMSMOCOMP (d_method); + long SearchEffort = self->search_effort; + int UseStrangeBob = self->strange_bob; + int IsOdd; + const unsigned char *pWeaveSrc; + const unsigned char *pWeaveSrcP; + unsigned char *pWeaveDest; + const unsigned char *pCopySrc; + const unsigned char *pCopySrcP; + unsigned char *pCopyDest; + int src_pitch; + int dst_pitch; + int rowsize; + int FldHeight; + + /* double stride do address just every odd/even scanline */ + src_pitch = object->field_stride; + dst_pitch = object->row_stride; + rowsize = object->row_stride; + FldHeight = object->field_height; + + pCopySrc = GST_BUFFER_DATA(object->field_history[object->history_count-1].buf); + pCopySrcP = GST_BUFFER_DATA(object->field_history[object->history_count-3].buf); + pWeaveSrc = GST_BUFFER_DATA(object->field_history[object->history_count-2].buf); + pWeaveSrcP = GST_BUFFER_DATA(object->field_history[object->history_count-4].buf); + + /* use bottom field and interlace top field */ + if (object->field_history[object->history_count-2].flags == PICTURE_INTERLACED_BOTTOM) { + IsOdd = 1; + + // if we have an odd field we copy an even field and weave an odd field + pCopyDest = GST_BUFFER_DATA(outbuf); + pWeaveDest = pCopyDest + dst_pitch; + } + /* do it vice verca */ + else { + + IsOdd = 0; + // if we have an even field we copy an odd field and weave an even field + pCopyDest = GST_BUFFER_DATA(outbuf) + dst_pitch; + pWeaveDest = GST_BUFFER_DATA(outbuf); + } + + + // copy 1st and last weave lines + Fieldcopy(pWeaveDest, pCopySrc, rowsize, + 1, dst_pitch*2, src_pitch); + Fieldcopy(pWeaveDest+(FldHeight-1)*dst_pitch*2, + pCopySrc+(FldHeight-1)*src_pitch, rowsize, + 1, dst_pitch*2, src_pitch); + +#ifdef USE_VERTICAL_FILTER + // Vertical Filter currently not implemented for DScaler !! + // copy 1st and last lines the copy field + Fieldcopy(pCopyDest, pCopySrc, rowsize, + 1, dst_pitch*2, src_pitch); + Fieldcopy(pCopyDest+(FldHeight-1)*dst_pitch*2, + pCopySrc+(FldHeight-1)*src_pitch, rowsize, + 1, dst_pitch*2, src_pitch); +#else + + // copy all of the copy field + Fieldcopy(pCopyDest, pCopySrc, rowsize, + FldHeight, dst_pitch*2, src_pitch); +#endif + // then go fill in the hard part, being variously lazy depending upon + // SearchEffort + + if(!UseStrangeBob) { + if (SearchEffort == 0) + { + SEFUNC(0); + } + else if (SearchEffort <= 1) + { + SEFUNC(1); + } + /* else if (SearchEffort <= 2) + { + SEFUNC(2); + } + */ + else if (SearchEffort <= 3) + { + SEFUNC(3); + } + else if (SearchEffort <= 5) + { + SEFUNC(5); + } + else if (SearchEffort <= 9) + { + SEFUNC(9); + } + else if (SearchEffort <= 11) + { + SEFUNC(11); + } + else if (SearchEffort <= 13) + { + SEFUNC(13); + } + else if (SearchEffort <= 15) + { + SEFUNC(15); + } + else if (SearchEffort <= 19) + { + SEFUNC(19); + } + else if (SearchEffort <= 21) + { + SEFUNC(21); + } + else + { + SEFUNC(Max); + } + } + else + { + if (SearchEffort == 0) + { + SEFUNC(0SB); + } + else if (SearchEffort <= 1) + { + SEFUNC(1SB); + } + /* else if (SearchEffort <= 2) + { + SEFUNC(2SB); + } + */ + else if (SearchEffort <= 3) + { + SEFUNC(3SB); + } + else if (SearchEffort <= 5) + { + SEFUNC(5SB); + } + else if (SearchEffort <= 9) + { + SEFUNC(9SB); + } + else if (SearchEffort <= 11) + { + SEFUNC(11SB); + } + else if (SearchEffort <= 13) + { + SEFUNC(13SB); + } + else if (SearchEffort <= 15) + { + SEFUNC(15SB); + } + else if (SearchEffort <= 19) + { + SEFUNC(19SB); + } + else if (SearchEffort <= 21) + { + SEFUNC(21SB); + } + else + { + SEFUNC(MaxSB); + } + } + +#if defined(BUILD_X86_ASM) && !defined(IS_C) + __asm__ __volatile__("emms"); +#endif +} diff --git a/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll2.inc b/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll2.inc new file mode 100644 index 00000000..f6344eab --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/TomsMoCompAll2.inc @@ -0,0 +1,243 @@ +// -*- c++ -*- + +#ifdef SEARCH_EFFORT_FUNC +#undef SEARCH_EFFORT_FUNC +#endif + +#ifdef USE_STRANGE_BOB +#define SEARCH_EFFORT_FUNC(n) SEFUNC(n##SB) +#else +#define SEARCH_EFFORT_FUNC(n) SEFUNC(n) +#endif + +static inline int SEARCH_EFFORT_FUNC(0) // we don't try at all ;-) +{ + //see Search_Effort_Max() for comments +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +} + +static inline int SEARCH_EFFORT_FUNC(1) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see Search_Effort_Max() for comments +#include "SearchLoopTop.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +static inline int SEARCH_EFFORT_FUNC(3) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see Search_Effort_Max() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA2.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +static inline int SEARCH_EFFORT_FUNC(5) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see Search_Effort_Max() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA2.inc" +#include "SearchLoopOddAH2.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// 3x3 search +static inline int SEARCH_EFFORT_FUNC(9) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchEffortMax() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoopVA.inc" +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// Search 9 with 2 H-half pels added +static inline int SEARCH_EFFORT_FUNC(11) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchEffortMax() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA.inc" +#include "SearchLoopOddAH2.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoopVA.inc" +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// Search 11 with 2 V-half pels added +static inline int SEARCH_EFFORT_FUNC(13) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchEffortMax() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA.inc" +#include "SearchLoopOddAH2.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoopVAH.inc" +#include "SearchLoopVA.inc" +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// 5x3 +static inline int SEARCH_EFFORT_FUNC(15) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchEffortMax() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoopEdgeA.inc" +#include "SearchLoopVA.inc" +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// 5x3 + 4 half pels +static inline int SEARCH_EFFORT_FUNC(19) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchEffortMax() for comments +#include "SearchLoopTop.inc" +#include "SearchLoopOddA.inc" +#include "SearchLoopOddAH2.inc" + RESET_CHROMA // pretend chroma diffs was 255 each +#include "SearchLoopEdgeA.inc" +#include "SearchLoopVAH.inc" +#include "SearchLoopVA.inc" +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// Handle one 4x1 block of pixels +// Search a 7x3 area, no half pels + +static inline int SEARCH_EFFORT_FUNC(21) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchLoopTop.inc for comments +#include "SearchLoopTop.inc" + + // odd addresses -- the pixels at odd address wouldn't generate + // good luma values but we will mask those off + +#include "SearchLoopOddA6.inc" // 4 odd v half pels, 3 to left & right +#include "SearchLoopOddA.inc" // 6 odd pels, 1 to left & right + + RESET_CHROMA // pretend chroma diffs was 255 each + + // even addresses -- use both luma and chroma from these + // search averages of 2 pixels left and right +#include "SearchLoopEdgeA.inc" + // search vertical line and averages, -1,0,+1 +#include "SearchLoopVA.inc" + // blend our results and loop +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +// Handle one 4x1 block of pixels +// Search a 9x3 area, no half pels +static inline int SEARCH_EFFORT_FUNC(Max) +{ +#ifdef IS_C +#define SKIP_SEARCH +#include "SearchLoopTop.inc" +#include "SearchLoopBottom.inc" +#undef SKIP_SEARCH +#else + //see SearchLoopTop.inc for comments +#include "SearchLoopTop.inc" + + // odd addresses -- the pixels at odd address wouldn't generate + // good luma values but we will mask those off + +#include "SearchLoopOddA6.inc" // 4 odd v half pels, 3 to left & right +#include "SearchLoopOddA.inc" // 6 odd pels, 1 to left & right + + RESET_CHROMA // pretend chroma diffs was 255 each + + // even addresses -- use both luma and chroma from these + // search averages of 4 pixels left and right +#include "SearchLoopEdgeA8.inc" + // search averages of 2 pixels left and right +#include "SearchLoopEdgeA.inc" + // search vertical line and averages, -1,0,+1 +#include "SearchLoopVA.inc" + // blend our results and loop +#include "SearchLoop0A.inc" +#include "SearchLoopBottom.inc" +#endif +} + +#undef SEARCH_EFFORT_FUNC + diff --git a/gst/deinterlace/tvtime/tomsmocomp/WierdBob.inc b/gst/deinterlace/tvtime/tomsmocomp/WierdBob.inc new file mode 100644 index 00000000..f4bbb830 --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/WierdBob.inc @@ -0,0 +1,286 @@ +// -*- c++ -*- + + // First, get and save our possible Bob values + // Assume our pixels are layed out as follows with x the calc'd bob value + // and the other pixels are from the current field + // + // j a b c k current field + // x calculated line + // m d e f n current field + // + // we calc the bob value as: + // x2 = either avg(a,f), avg(c,d), avg(b,e), avg(j,n), or avg(k,m) + + // selected for the smallest of abs(a,f), abs(c,d), or abs(b,e), etc. + +#ifndef IS_C + // a,f + "movq -2(%%"XBX"), %%mm0\n\t" // value a from top left + "movq 2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f from bottom right + "movq %%mm0, %%mm6\n\t" +// pavgb %%mm6, %%mm1 // avg(a,f), also best so far + V_PAVGB ("%%mm6", "%%mm1", "%%mm7", _ShiftMask) // avg(a,f), also best so far + "movq %%mm0, %%mm7\n\t" + "psubusb %%mm1, %%mm7\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm7\n\t" // abs diff, also best so far + + // c,d + "movq 2(%%"XBX"), %%mm0\n\t" // value a from top left + "movq -2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f from bottom right + "movq %%mm0, %%mm2\n\t" +// pavgb %%mm2, %%mm1 // avg(c,d) + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(c,d) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(c,d) + "movq %%mm3, %%mm1\n\t" // keep copy + + "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 + + "pand %%mm3, %%mm1\n\t" // keep only better new avg and abs + "pand %%mm3, %%mm2\n\t" + + "pand %%mm4, %%mm6\n\t" + "pand %%mm4, %%mm7\n\t" + + "por %%mm2, %%mm6\n\t" // and merge new & old vals keeping best + "por %%mm1, %%mm7\n\t" + "por "_UVMask", %%mm7\n\t" // but we know chroma is worthless so far + "pand "_YMask", %%mm5\n\t" // mask out chroma from here also + + // j,n + "movq -4(%%"XBX"), %%mm0\n\t" // value j from top left + "movq 4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n from bottom right + "movq %%mm0, %%mm2\n\t" +// pavgb %%mm2, %%mm1 // avg(j,n) + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(j,n) + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(j-n) + "movq %%mm3, %%mm1\n\t" // keep copy + + "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 + + "pand %%mm3, %%mm1\n\t" // keep only better new avg and abs + "pand %%mm2, %%mm3\n\t" + + "pand %%mm4, %%mm6\n\t" + "pand %%mm4, %%mm7\n\t" + + "por %%mm3, %%mm6\n\t" // and merge new & old vals keeping best + "por %%mm1, %%mm7\n\t" // " + + // k, m + "movq 4(%%"XBX"), %%mm0\n\t" // value k from top right + "movq -4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n from bottom left + "movq %%mm0, %%mm4\n\t" +// pavgb %%mm4, %%mm1 // avg(k,m) + V_PAVGB ("%%mm4", "%%mm1", "%%mm3", _ShiftMask) // avg(k,m) + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(k,m) + "movq %%mm3, %%mm1\n\t" // keep copy + + "movq %%mm4, %%mm2\n\t" // avg(k,m) + + "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 + + "pand %%mm3, %%mm1\n\t" // keep only better new avg and abs + "pand %%mm2, %%mm3\n\t" + + "pand %%mm4, %%mm6\n\t" + "pand %%mm4, %%mm7\n\t" + + "por %%mm3, %%mm6\n\t" // and merge new & old vals keeping best + "por %%mm1, %%mm7\n\t" // " + + // b,e + "movq (%%"XBX"), %%mm0\n\t" // value b from top + "movq (%%"XBX", %%"XCX"), %%mm1\n\t" // value e from bottom + +// We will also calc here the max/min values to later limit comb +// so the max excursion will not exceed the Max_Comb constant + +#ifdef SKIP_SEARCH + "movq %%mm0, %%mm2\n\t" +// pminub %%mm2, %%mm1 + V_PMINUB ("%%mm2", "%%mm1", "%%mm4") + +// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this + V_PMAXUB ("%%mm6", "%%mm2") + "movq %%mm0, %%mm2\n\t" + V_PMAXUB ("%%mm2", "%%mm1") +// pminub %%mm6, %%mm2 // clip our current results so far to be below this + V_PMINUB ("%%mm6", "%%mm2", "%%mm4") + +#else + "movq %%mm0, %%mm2\n\t" + "movq (%%"XAX"), %%mm4\n\t" + "psubusb %%mm4, %%mm2\n\t" + "psubusb %%mm0, %%mm4\n\t" + "por %%mm2, %%mm4\n\t" // abs diff + + "movq %%mm1, %%mm2\n\t" + "movq (%%"XAX", %%"XCX"), %%mm3\n\t" + "psubusb %%mm3, %%mm2\n\t" + "psubusb %%mm1, %%mm3\n\t" + "por %%mm2, %%mm3\n\t" // abs diff +// pmaxub %%mm3, %%mm4 // top or bottom pixel moved most + V_PMAXUB ("%%mm3", "%%mm4") // top or bottom pixel moved most + "psubusb "_Max_Mov", %%mm3\n\t" // moved more than allowed? or goes to 0? + "pxor %%mm4, %%mm4\n\t" + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where low motion, else high motion + + "movq %%mm0, %%mm2\n\t" +// pminub %%mm2, %%mm1 + V_PMINUB ("%%mm2", "%%mm1", "%%mm4") + +// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this + V_PMAXUB ("%%mm6", "%%mm2") + + "psubusb %%mm3, %%mm2\n\t" // maybe decrease it to 0000.. if no surround motion + "movq %%mm2, "_Min_Vals"\n\t" + + "movq %%mm0, %%mm2\n\t" + V_PMAXUB ("%%mm2", "%%mm1") +// pminub %%mm6, %%mm2 // clip our current results so far to be below this + V_PMINUB ("%%mm6", "%%mm2", "%%mm4") + "paddusb %%mm3, %%mm2\n\t" // maybe increase it to ffffff if no surround motion + "movq %%mm2, "_Max_Vals"\n\t" +#endif + + "movq %%mm0, %%mm2\n\t" +// pavgb %%mm2, %%mm1 // avg(b,e) + V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(b,e) + + "movq %%mm0, %%mm3\n\t" + "psubusb %%mm1, %%mm3\n\t" + "psubusb %%mm0, %%mm1\n\t" + "por %%mm1, %%mm3\n\t" // abs(c,d) + "movq %%mm3, %%mm1\n\t" // keep copy of diffs + + "pxor %%mm4, %%mm4\n\t" + "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 + "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 + + "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 + + "pand %%mm3, %%mm1\n\t" + "pand %%mm3, %%mm2\n\t" + + "pand %%mm4, %%mm6\n\t" + "pand %%mm4, %%mm7\n\t" + + "por %%mm2, %%mm6\n\t" // our x2 value + "por %%mm1, %%mm7\n\t" // our x2 diffs + "movq %%mm7, %%mm4\n\t" // save as bob uncertainty indicator + +#else + + // a,f + best[0] = (pBob[-2] + pBob[src_pitch2 + 2]) / 2; + diff[0] = ABS (pBob[-2] - pBob[src_pitch2 + 2]); + best[1] = (pBob[-1] + pBob[src_pitch2 + 3]) / 2; + diff[1] = ABS (pBob[-1] - pBob[src_pitch2 + 3]); + + // c,d + if (ABS (pBob[2] - pBob[src_pitch2 - 2]) < diff[0]) { + best[0] = (pBob[2] + pBob[src_pitch2 - 2]) / 2; + diff[0] = ABS (pBob[2] - pBob[src_pitch2 - 2]); + } + + if (ABS (pBob[3] - pBob[src_pitch2 - 1]) < diff[1]) { + best[1] = (pBob[3] + pBob[src_pitch2 - 1]) / 2; + diff[1] = ABS (pBob[3] - pBob[src_pitch2 - 1]); + } + + // j,n + if (ABS (pBob[-4] - pBob[src_pitch2 + 4]) < diff[0]) { + best[0] = (pBob[-4] + pBob[src_pitch2 + 4]) / 2; + diff[0] = ABS (pBob[-4] - pBob[src_pitch2 + 4]); + } + + if (ABS (pBob[-3] - pBob[src_pitch2 + 5]) < diff[1]) { + best[1] = (pBob[-3] + pBob[src_pitch2 + 5]) / 2; + diff[1] = ABS (pBob[-3] - pBob[src_pitch2 + 5]); + } + + // k,m + if (ABS (pBob[4] - pBob[src_pitch2 - 4]) < diff[0]) { + best[0] = (pBob[4] + pBob[src_pitch2 - 4]) / 2; + diff[0] = ABS (pBob[-4] - pBob[src_pitch2 - 4]); + } + + if (ABS (pBob[5] - pBob[src_pitch2 - 3]) < diff[1]) { + best[1] = (pBob[5] + pBob[src_pitch2 - 3]) / 2; + diff[1] = ABS (pBob[-3] - pBob[src_pitch2 - 3]); + } + // k,m + if (ABS (pBob[4] - pBob[src_pitch2 - 4]) < diff[0]) { + best[0] = (pBob[4] + pBob[src_pitch2 - 4]) / 2; + diff[0] = ABS (pBob[-4] - pBob[src_pitch2 - 4]); + } + + if (ABS (pBob[5] - pBob[src_pitch2 - 3]) < diff[1]) { + best[1] = (pBob[5] + pBob[src_pitch2 - 3]) / 2; + diff[1] = ABS (pBob[-3] - pBob[src_pitch2 - 3]); + } + +// We will also calc here the max/min values to later limit comb +// so the max excursion will not exceed the Max_Comb constant + +#ifdef SKIP_SEARCH + best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); + best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); +#else + mov[0] = MAX (ABS (pBob[0] - pBobP[0]), ABS (pBob[src_pitch2] - pBobP[src_pitch2])); + mov[1] = MAX (ABS (pBob[1] - pBobP[1]), ABS (pBob[src_pitch2 + 1] - pBobP[src_pitch2 + 1])); + + MinVals[0] = 0; + MinVals[1] = 0; + MaxVals[0] = 255; + MaxVals[1] = 255; + + if (mov[0] > Max_Mov[0]) { + MinVals[0] = MAX (MIN (pBob[0], pBob[src_pitch2]), best[0]); + MaxVals[0] = MIN (MAX (pBob[0], pBob[src_pitch2]), best[0]); + } + + if (mov[1] > Max_Mov[1]) { + MinVals[1] = MAX (MIN (pBob[1], pBob[src_pitch2 + 1]), best[1]); + MaxVals[1] = MIN (MAX (pBob[1], pBob[src_pitch2 + 1]), best[1]); + } + + best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); + best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); +#endif + + avg[0] = (pBob[src_pitch2] + pBob[0]) / 2; + avg[1] = (pBob[src_pitch2 + 1] + pBob[1]) / 2; + diff2[0] = ABS (pBob[src_pitch2] - pBob[0]); + diff2[1] = ABS (pBob[src_pitch2 + 1] - pBob[1]); + + if (diff2[0] < diff[0]) { + best[0] = avg[0]; + diff[0] = diff2[0]; + } + + if (diff2[1] < diff[1]) { + best[1] = avg[1]; + diff[1] = diff2[1]; + } +#endif diff --git a/gst/deinterlace/tvtime/tomsmocomp/tomsmocompmacros.h b/gst/deinterlace/tvtime/tomsmocomp/tomsmocompmacros.h new file mode 100644 index 00000000..7e8147ec --- /dev/null +++ b/gst/deinterlace/tvtime/tomsmocomp/tomsmocompmacros.h @@ -0,0 +1,164 @@ +#include +#include + +// Define a few macros for CPU dependent instructions. +// I suspect I don't really understand how the C macro preprocessor works but +// this seems to get the job done. // TRB 7/01 + +// BEFORE USING THESE YOU MUST SET: + +// #define SIMD_TYPE MMXEXT (or MMX or 3DNOW) + +// some macros for pavgb instruction +// V_PAVGB(mmr1, mmr2, mmr work register, smask) mmr2 may = mmrw if you can trash it + +#define V_PAVGB_MMX(mmr1, mmr2, mmrw, smask) \ + "movq "mmr2", "mmrw"\n\t" \ + "pand "smask", "mmrw"\n\t" \ + "psrlw $1, "mmrw"\n\t" \ + "pand "smask", "mmr1"\n\t" \ + "psrlw $1, "mmr1"\n\t" \ + "paddusb "mmrw", "mmr1"\n\t" +#define V_PAVGB_MMXEXT(mmr1, mmr2, mmrw, smask) "pavgb "mmr2", "mmr1"\n\t" +#define V_PAVGB_3DNOW(mmr1, mmr2, mmrw, smask) "pavgusb "mmr2", "mmr1"\n\t" +#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SIMD_TYPE) +#define V_PAVGB2(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) +#define V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB_##simd_type(mmr1, mmr2, mmrw, smask) + +// some macros for pmaxub instruction +#define V_PMAXUB_MMX(mmr1, mmr2) \ + "psubusb "mmr2", "mmr1"\n\t" \ + "paddusb "mmr2", "mmr1"\n\t" +#define V_PMAXUB_MMXEXT(mmr1, mmr2) "pmaxub "mmr2", "mmr1"\n\t" +#define V_PMAXUB_3DNOW(mmr1, mmr2) V_PMAXUB_MMX(mmr1, mmr2) // use MMX version +#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SIMD_TYPE) +#define V_PMAXUB2(mmr1, mmr2, simd_type) V_PMAXUB3(mmr1, mmr2, simd_type) +#define V_PMAXUB3(mmr1, mmr2, simd_type) V_PMAXUB_##simd_type(mmr1, mmr2) + +// some macros for pminub instruction +// V_PMINUB(mmr1, mmr2, mmr work register) mmr2 may NOT = mmrw +#define V_PMINUB_MMX(mmr1, mmr2, mmrw) \ + "pcmpeqb "mmrw", "mmrw"\n\t" \ + "psubusb "mmr2", "mmrw"\n\t" \ + "paddusb "mmrw", "mmr1"\n\t" \ + "psubusb "mmrw", "mmr1"\n\t" +#define V_PMINUB_MMXEXT(mmr1, mmr2, mmrw) "pminub "mmr2", "mmr1"\n\t" +#define V_PMINUB_3DNOW(mmr1, mmr2, mmrw) V_PMINUB_MMX(mmr1, mmr2, mmrw) // use MMX version +#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SIMD_TYPE) +#define V_PMINUB2(mmr1, mmr2, mmrw, simd_type) V_PMINUB3(mmr1, mmr2, mmrw, simd_type) +#define V_PMINUB3(mmr1, mmr2, mmrw, simd_type) V_PMINUB_##simd_type(mmr1, mmr2, mmrw) + +// some macros for movntq instruction +// V_MOVNTQ(mmr1, mmr2) +#define V_MOVNTQ_MMX(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" +#define V_MOVNTQ_3DNOW(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" +#define V_MOVNTQ_MMXEXT(mmr1, mmr2) "movntq "mmr2", "mmr1"\n\t" +#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SIMD_TYPE) +#define V_MOVNTQ2(mmr1, mmr2, simd_type) V_MOVNTQ3(mmr1, mmr2, simd_type) +#define V_MOVNTQ3(mmr1, mmr2, simd_type) V_MOVNTQ_##simd_type(mmr1, mmr2) + +// end of macros + +#ifdef IS_SSE2 + +#define MERGE4PIXavg(PADDR1, PADDR2) \ + "movdqu "PADDR1", %%xmm0\n\t" /* our 4 pixels */ \ + "movdqu "PADDR2", %%xmm1\n\t" /* our pixel2 value */ \ + "movdqa %%xmm0, %%xmm2\n\t" /* another copy of our pixel1 value */ \ + "movdqa %%xmm1, %%xmm3\n\t" /* another copy of our pixel1 value */ \ + "psubusb %%xmm1, %%xmm2\n\t" \ + "psubusb %%xmm0, %%xmm3\n\t" \ + "por %%xmm3, %%xmm2\n\t" \ + "pavgb %%xmm1, %%xmm0\n\t" /* avg of 2 pixels */ \ + "movdqa %%xmm2, %%xmm3\n\t" /* another copy of our our weights */ \ + "pxor %%xmm1, %%xmm1\n\t" \ + "psubusb %%xmm7, %%xmm3\n\t" /* nonzero where old weights lower, else 0 */ \ + "pcmpeqb %%xmm1, %%xmm3\n\t" /* now ff where new better, else 00 */ \ + "pcmpeqb %%xmm3, %%xmm1\n\t" /* here ff where old better, else 00 */ \ + "pand %%xmm3, %%xmm0\n\t" /* keep only better new pixels */ \ + "pand %%xmm3, %%xmm2\n\t" /* and weights */ \ + "pand %%xmm1, %%xmm5\n\t" /* keep only better old pixels */ \ + "pand %%xmm1, %%xmm7\n\t" \ + "por %%xmm0, %%xmm5\n\t" /* and merge new & old vals */ \ + "por %%xmm2, %%xmm7\n\t" + +#define MERGE4PIXavgH(PADDR1A, PADDR1B, PADDR2A, PADDR2B) \ + "movdqu "PADDR1A", %%xmm0\n\t" /* our 4 pixels */ \ + "movdqu "PADDR2A", %%xmm1\n\t" /* our pixel2 value */ \ + "movdqu "PADDR1B", %%xmm2\n\t" /* our 4 pixels */ \ + "movdqu "PADDR2B", %%xmm3\n\t" /* our pixel2 value */ \ + "pavgb %%xmm2, %%xmm0\n\t" \ + "pavgb %%xmm3, %%xmm1\n\t" \ + "movdqa %%xmm0, %%xmm2\n\t" /* another copy of our pixel1 value */ \ + "movdqa %%xmm1, %%xmm3\n\t" /* another copy of our pixel1 value */ \ + "psubusb %%xmm1, %%xmm2\n\t" \ + "psubusb %%xmm0, %%xmm3\n\t" \ + "por %%xmm3, %%xmm2\n\t" \ + "pavgb %%xmm1, %%xmm0\n\t" /* avg of 2 pixels */ \ + "movdqa %%xmm2, %%xmm3\n\t" /* another copy of our our weights */ \ + "pxor %%xmm1, %%xmm1\n\t" \ + "psubusb %%xmm7, %%xmm3\n\t" /* nonzero where old weights lower, else 0 */ \ + "pcmpeqb %%xmm1, %%xmm3\n\t" /* now ff where new better, else 00 */ \ + "pcmpeqb %%xmm3, %%xmm1\n\t" /* here ff where old better, else 00 */ \ + "pand %%xmm3, %%xmm0\n\t" /* keep only better new pixels */ \ + "pand %%xmm3, %%xmm2\n\t" /* and weights */ \ + "pand %%xmm1, %%xmm5\n\t" /* keep only better old pixels */ \ + "pand %%xmm1, %%xmm7\n\t" \ + "por %%xmm0, %%xmm5\n\t" /* and merge new & old vals */ \ + "por %%xmm2, %%xmm7\n\t" + +#define RESET_CHROMA "por "_UVMask", %%xmm7\n\t" + +#else // ifdef IS_SSE2 + +#define MERGE4PIXavg(PADDR1, PADDR2) \ + "movq "PADDR1", %%mm0\n\t" /* our 4 pixels */ \ + "movq "PADDR2", %%mm1\n\t" /* our pixel2 value */ \ + "movq %%mm0, %%mm2\n\t" /* another copy of our pixel1 value */ \ + "movq %%mm1, %%mm3\n\t" /* another copy of our pixel1 value */ \ + "psubusb %%mm1, %%mm2\n\t" \ + "psubusb %%mm0, %%mm3\n\t" \ + "por %%mm3, %%mm2\n\t" \ + V_PAVGB ("%%mm0", "%%mm1", "%%mm3", _ShiftMask) /* avg of 2 pixels */ \ + "movq %%mm2, %%mm3\n\t" /* another copy of our our weights */ \ + "pxor %%mm1, %%mm1\n\t" \ + "psubusb %%mm7, %%mm3\n\t" /* nonzero where old weights lower, else 0 */ \ + "pcmpeqb %%mm1, %%mm3\n\t" /* now ff where new better, else 00 */ \ + "pcmpeqb %%mm3, %%mm1\n\t" /* here ff where old better, else 00 */ \ + "pand %%mm3, %%mm0\n\t" /* keep only better new pixels */ \ + "pand %%mm3, %%mm2\n\t" /* and weights */ \ + "pand %%mm1, %%mm5\n\t" /* keep only better old pixels */ \ + "pand %%mm1, %%mm7\n\t" \ + "por %%mm0, %%mm5\n\t" /* and merge new & old vals */ \ + "por %%mm2, %%mm7\n\t" + +#define MERGE4PIXavgH(PADDR1A, PADDR1B, PADDR2A, PADDR2B) \ + "movq "PADDR1A", %%mm0\n\t" /* our 4 pixels */ \ + "movq "PADDR2A", %%mm1\n\t" /* our pixel2 value */ \ + "movq "PADDR1B", %%mm2\n\t" /* our 4 pixels */ \ + "movq "PADDR2B", %%mm3\n\t" /* our pixel2 value */ \ + V_PAVGB("%%mm0", "%%mm2", "%%mm2", _ShiftMask) \ + V_PAVGB("%%mm1", "%%mm3", "%%mm3", _ShiftMask) \ + "movq %%mm0, %%mm2\n\t" /* another copy of our pixel1 value */ \ + "movq %%mm1, %%mm3\n\t" /* another copy of our pixel1 value */ \ + "psubusb %%mm1, %%mm2\n\t" \ + "psubusb %%mm0, %%mm3\n\t" \ + "por %%mm3, %%mm2\n\t" \ + V_PAVGB("%%mm0", "%%mm1", "%%mm3", _ShiftMask) /* avg of 2 pixels */ \ + "movq %%mm2, %%mm3\n\t" /* another copy of our our weights */ \ + "pxor %%mm1, %%mm1\n\t" \ + "psubusb %%mm7, %%mm3\n\t" /* nonzero where old weights lower, else 0 */ \ + "pcmpeqb %%mm1, %%mm3\n\t" /* now ff where new better, else 00 */ \ + "pcmpeqb %%mm3, %%mm1\n\t" /* here ff where old better, else 00 */ \ + "pand %%mm3, %%mm0\n\t" /* keep only better new pixels */ \ + "pand %%mm3, %%mm2\n\t" /* and weights */ \ + "pand %%mm1, %%mm5\n\t" /* keep only better old pixels */ \ + "pand %%mm1, %%mm7\n\t" \ + "por %%mm0, %%mm5\n\t" /* and merge new & old vals */ \ + "por %%mm2, %%mm7\n\t" + +#define RESET_CHROMA "por "_UVMask", %%mm7\n\t" + +#endif + + diff --git a/gst/deinterlace/tvtime/vfir.c b/gst/deinterlace/tvtime/vfir.c new file mode 100644 index 00000000..b3ebaae1 --- /dev/null +++ b/gst/deinterlace/tvtime/vfir.c @@ -0,0 +1,187 @@ +/* + * + * GStreamer + * Copyright (C) 2004 Billy Biggs + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This file contains code from ffmpeg, see http://ffmpeg.org/ (LGPL) + * and modifications by Billy Biggs. + * + * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs. + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_VFIR (gst_deinterlace_method_vfir_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR)) +#define GST_IS_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR)) +#define GST_DEINTERLACE_METHOD_VFIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass)) +#define GST_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIR)) +#define GST_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass)) +#define GST_DEINTERLACE_METHOD_VFIR_CAST(obj) ((GstDeinterlaceMethodVFIR*)(obj)) + +GType gst_deinterlace_method_vfir_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodVFIR; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodVFIRClass; + +/* + * 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]. + */ + +/** + * C implementation. + */ +static inline void +deinterlace_line_c (GstDeinterlaceMethod * self, GstDeinterlace * parent, + guint8 * dst, GstDeinterlaceScanlineData * scanlines, gint width) +{ + gint sum; + guint8 *lum_m4 = scanlines->tt1; + guint8 *lum_m3 = scanlines->t0; + guint8 *lum_m2 = scanlines->m1; + guint8 *lum_m1 = scanlines->b0; + guint8 *lum = scanlines->bb1; + gint size = width * 2; + + 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++; + } +} + +#ifdef BUILD_X86_ASM +#include "mmx.h" +static void +deinterlace_line_mmx (GstDeinterlaceMethod * self, GstDeinterlace * parent, + guint8 * dst, GstDeinterlaceScanlineData * scanlines, gint width) +{ + mmx_t rounder; + guint8 *lum_m4 = scanlines->tt1; + guint8 *lum_m3 = scanlines->t0; + guint8 *lum_m2 = scanlines->m1; + guint8 *lum_m1 = scanlines->b0; + guint8 *lum = scanlines->bb1; + + 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 (; width > 1; width -= 2) { + movd_m2r (*lum_m4, mm0); + movd_m2r (*lum_m3, mm1); + movd_m2r (*lum_m2, mm2); + movd_m2r (*lum_m1, mm3); + movd_m2r (*lum, 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); + lum_m4 += 4; + lum_m3 += 4; + lum_m2 += 4; + lum_m1 += 4; + lum += 4; + dst += 4; + } + emms (); + + /* Handle odd widths */ + if (width > 0) { + scanlines->tt1 = lum_m4; + scanlines->t0 = lum_m3; + scanlines->m1 = lum_m2; + scanlines->b0 = lum_m1; + scanlines->bb1 = lum; + + deinterlace_line_c (self, parent, dst, scanlines, width); + } +} +#endif + +G_DEFINE_TYPE (GstDeinterlaceMethodVFIR, gst_deinterlace_method_vfir, + GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void +gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; +#ifdef BUILD_X86_ASM + guint cpu_flags = oil_cpu_get_flags (); +#endif + + dim_class->fields_required = 2; + dim_class->name = "Blur Vertical"; + dim_class->nick = "vfir"; + dim_class->latency = 0; + +#ifdef BUILD_X86_ASM + if (cpu_flags & OIL_IMPL_FLAG_MMX) { + dism_class->interpolate_scanline = deinterlace_line_mmx; + } else { + dism_class->interpolate_scanline = deinterlace_line_c; + } +#else + dism_class->interpolate_scanline = deinterlace_line_c; +#endif +} + +static void +gst_deinterlace_method_vfir_init (GstDeinterlaceMethodVFIR * self) +{ +} diff --git a/gst/deinterlace/tvtime/weave.c b/gst/deinterlace/tvtime/weave.c new file mode 100644 index 00000000..1a86170e --- /dev/null +++ b/gst/deinterlace/tvtime/weave.c @@ -0,0 +1,82 @@ +/** + * Weave frames + * Copyright (C) 2002 Billy Biggs . + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_WEAVE (gst_deinterlace_method_weave_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_WEAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE)) +#define GST_IS_DEINTERLACE_METHOD_WEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE)) +#define GST_DEINTERLACE_METHOD_WEAVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE, GstDeinterlaceMethodWeaveClass)) +#define GST_DEINTERLACE_METHOD_WEAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE, GstDeinterlaceMethodWeave)) +#define GST_DEINTERLACE_METHOD_WEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE, GstDeinterlaceMethodWeaveClass)) +#define GST_DEINTERLACE_METHOD_WEAVE_CAST(obj) ((GstDeinterlaceMethodWeave*)(obj)) + +GType gst_deinterlace_method_weave_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeave; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveClass; + + +static void +deinterlace_scanline_weave (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->m1, parent->row_stride); +} + +static void +copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace * parent, + guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->m0, parent->row_stride); +} + +G_DEFINE_TYPE (GstDeinterlaceMethodWeave, gst_deinterlace_method_weave, + GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void +gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; + + dim_class->fields_required = 2; + dim_class->name = "Weave"; + dim_class->nick = "weave"; + dim_class->latency = 0; + + dism_class->interpolate_scanline = deinterlace_scanline_weave; + dism_class->copy_scanline = copy_scanline; +} + +static void +gst_deinterlace_method_weave_init (GstDeinterlaceMethodWeave * self) +{ +} diff --git a/gst/deinterlace/tvtime/weavebff.c b/gst/deinterlace/tvtime/weavebff.c new file mode 100644 index 00000000..eb983cf2 --- /dev/null +++ b/gst/deinterlace/tvtime/weavebff.c @@ -0,0 +1,88 @@ +/** + * Weave frames, bottom-field-first. + * Copyright (C) 2003 Billy Biggs . + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF (gst_deinterlace_method_weave_bff_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_WEAVE_BFF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF)) +#define GST_IS_DEINTERLACE_METHOD_WEAVE_BFF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF)) +#define GST_DEINTERLACE_METHOD_WEAVE_BFF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF, GstDeinterlaceMethodWeaveBFFClass)) +#define GST_DEINTERLACE_METHOD_WEAVE_BFF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF, GstDeinterlaceMethodWeaveBFF)) +#define GST_DEINTERLACE_METHOD_WEAVE_BFF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF, GstDeinterlaceMethodWeaveBFFClass)) +#define GST_DEINTERLACE_METHOD_WEAVE_BFF_CAST(obj) ((GstDeinterlaceMethodWeaveBFF*)(obj)) + +GType gst_deinterlace_method_weave_bff_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeaveBFF; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveBFFClass; + + +static void +deinterlace_scanline_weave (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->m1, parent->row_stride); +} + +static void +copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace * parent, + guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width) +{ + /* FIXME: original code used m2 and m0 but this looks really bad */ + if (scanlines->bottom_field) { + oil_memcpy (out, scanlines->bb2, parent->row_stride); + } else { + oil_memcpy (out, scanlines->bb0, parent->row_stride); + } +} + +G_DEFINE_TYPE (GstDeinterlaceMethodWeaveBFF, gst_deinterlace_method_weave_bff, + GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void +gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass * + klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; + + dim_class->fields_required = 3; + dim_class->name = "Progressive: Bottom Field First"; + dim_class->nick = "weavebff"; + dim_class->latency = 0; + + dism_class->interpolate_scanline = deinterlace_scanline_weave; + dism_class->copy_scanline = copy_scanline; +} + +static void +gst_deinterlace_method_weave_bff_init (GstDeinterlaceMethodWeaveBFF * self) +{ +} diff --git a/gst/deinterlace/tvtime/weavetff.c b/gst/deinterlace/tvtime/weavetff.c new file mode 100644 index 00000000..4885b63b --- /dev/null +++ b/gst/deinterlace/tvtime/weavetff.c @@ -0,0 +1,88 @@ +/** + * Weave frames, top-field-first. + * Copyright (C) 2003 Billy Biggs . + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "_stdint.h" +#include "gstdeinterlace.h" +#include + +#define GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF (gst_deinterlace_method_weave_tff_get_type ()) +#define GST_IS_DEINTERLACE_METHOD_WEAVE_TFF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF)) +#define GST_IS_DEINTERLACE_METHOD_WEAVE_TFF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF)) +#define GST_DEINTERLACE_METHOD_WEAVE_TFF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF, GstDeinterlaceMethodWeaveTFFClass)) +#define GST_DEINTERLACE_METHOD_WEAVE_TFF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF, GstDeinterlaceMethodWeaveTFF)) +#define GST_DEINTERLACE_METHOD_WEAVE_TFF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF, GstDeinterlaceMethodWeaveTFFClass)) +#define GST_DEINTERLACE_METHOD_WEAVE_TFF_CAST(obj) ((GstDeinterlaceMethodWeaveTFF*)(obj)) + +GType gst_deinterlace_method_weave_tff_get_type (void); + +typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeaveTFF; + +typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveTFFClass; + + +static void +deinterlace_scanline_weave (GstDeinterlaceMethod * self, + GstDeinterlace * parent, guint8 * out, + GstDeinterlaceScanlineData * scanlines, gint width) +{ + oil_memcpy (out, scanlines->m1, parent->row_stride); +} + +static void +copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace * parent, + guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width) +{ + /* FIXME: original code used m2 and m0 but this looks really bad */ + if (scanlines->bottom_field) { + oil_memcpy (out, scanlines->bb0, parent->row_stride); + } else { + oil_memcpy (out, scanlines->bb2, parent->row_stride); + } +} + +G_DEFINE_TYPE (GstDeinterlaceMethodWeaveTFF, gst_deinterlace_method_weave_tff, + GST_TYPE_DEINTERLACE_SIMPLE_METHOD); + +static void +gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass * + klass) +{ + GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; + GstDeinterlaceSimpleMethodClass *dism_class = + (GstDeinterlaceSimpleMethodClass *) klass; + + dim_class->fields_required = 3; + dim_class->name = "Progressive: Top Field First"; + dim_class->nick = "weavetff"; + dim_class->latency = 0; + + dism_class->interpolate_scanline = deinterlace_scanline_weave; + dism_class->copy_scanline = copy_scanline; +} + +static void +gst_deinterlace_method_weave_tff_init (GstDeinterlaceMethodWeaveTFF * self) +{ +} diff --git a/gst/deinterlace/tvtime/x86-64_macros.inc b/gst/deinterlace/tvtime/x86-64_macros.inc new file mode 100644 index 00000000..2e9df758 --- /dev/null +++ b/gst/deinterlace/tvtime/x86-64_macros.inc @@ -0,0 +1,82 @@ +/* + * + * GStreamer + * Copyright (C) 2004 Dirk Ziegelmeier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * + * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 + */ + +/* + * This file is copied from TVTIME's sources. + * Original author: Achim Schneider + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef XAX + +#if defined (HAVE_CPU_I386) && !defined(HAVE_CPU_X86_64) + +#define XAX "eax" +#define XBX "ebx" +#define XCX "ecx" +#define XDX "edx" +#define XSI "esi" +#define XDI "edi" +#define XSP "esp" +#define MOVX "movl" +#define LEAX "leal" +#define DECX "decl" +#define PUSHX "pushl" +#define POPX "popl" +#define CMPX "cmpl" +#define ADDX "addl" +#define SHLX "shll" +#define SHRX "shrl" +#define SUBX "subl" + +#elif defined (HAVE_CPU_X86_64) + +#define XAX "rax" +#define XBX "rbx" +#define XCX "rcx" +#define XDX "rdx" +#define XSI "rsi" +#define XDI "rdi" +#define XSP "rsp" +#define MOVX "movq" +#define LEAX "leaq" +#define DECX "decq" +#define PUSHX "pushq" +#define POPX "popq" +#define CMPX "cmpq" +#define ADDX "addq" +#define SHLX "shlq" +#define SHRX "shrq" +#define SUBX "subq" + +#else +#error Undefined architecture. Define either ARCH_X86 or ARCH_X86_64. +#endif + +#endif diff --git a/gst/deinterlace2/Makefile.am b/gst/deinterlace2/Makefile.am deleted file mode 100644 index 1de59919..00000000 --- a/gst/deinterlace2/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -plugin_LTLIBRARIES = libgstdeinterlace2.la - -libgstdeinterlace2_la_SOURCES = \ - gstdeinterlace2.c \ - tvtime/greedy.c \ - tvtime/greedyh.c \ - tvtime/vfir.c \ - tvtime/tomsmocomp.c \ - tvtime/weavetff.c \ - tvtime/weavebff.c \ - tvtime/weave.c \ - tvtime/linear.c \ - tvtime/linearblend.c \ - tvtime/scalerbob.c - -libgstdeinterlace2_la_CFLAGS = $(GST_CFLAGS) \ - $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(LIBOIL_CFLAGS) -libgstdeinterlace2_la_LIBADD = $(GST_LIBS) \ - $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(LIBOIL_LIBS) -libgstdeinterlace2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstdeinterlace2_la_LIBTOOLFLAGS = --tag=disable-static - -noinst_HEADERS = \ - gstdeinterlace2.h \ - tvtime/mmx.h \ - tvtime/sse.h \ - tvtime/greedyh.asm \ - tvtime/greedyhmacros.h \ - tvtime/plugins.h \ - tvtime/x86-64_macros.inc \ - tvtime/tomsmocomp/SearchLoop0A.inc \ - tvtime/tomsmocomp/SearchLoopBottom.inc \ - tvtime/tomsmocomp/SearchLoopEdgeA8.inc \ - tvtime/tomsmocomp/SearchLoopEdgeA.inc \ - tvtime/tomsmocomp/SearchLoopOddA2.inc \ - tvtime/tomsmocomp/SearchLoopOddA6.inc \ - tvtime/tomsmocomp/SearchLoopOddAH2.inc \ - tvtime/tomsmocomp/SearchLoopOddAH.inc \ - tvtime/tomsmocomp/SearchLoopOddA.inc \ - tvtime/tomsmocomp/SearchLoopTop.inc \ - tvtime/tomsmocomp/SearchLoopVAH.inc \ - tvtime/tomsmocomp/SearchLoopVA.inc \ - tvtime/tomsmocomp/StrangeBob.inc \ - tvtime/tomsmocomp/TomsMoCompAll2.inc \ - tvtime/tomsmocomp/TomsMoCompAll.inc \ - tvtime/tomsmocomp/tomsmocompmacros.h \ - tvtime/tomsmocomp/WierdBob.inc - diff --git a/gst/deinterlace2/gstdeinterlace2.c b/gst/deinterlace2/gstdeinterlace2.c deleted file mode 100644 index 42a69240..00000000 --- a/gst/deinterlace2/gstdeinterlace2.c +++ /dev/null @@ -1,1517 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2005 Martin Eikermann - * Copyright (C) 2008-2009 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-deinterlace2 - * - * deinterlace2 deinterlaces interlaced video frames to progressive video frames. - * For this different algorithms can be selected which will be described later. - * - * - * Example launch line - * |[ - * gst-launch -v filesrc location=/path/to/file ! decodebin2 ! ffmpegcolorspace ! deinterlace2 ! ffmpegcolorspace ! autovideosink - * ]| This pipeline deinterlaces a video file with the default deinterlacing options. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gstdeinterlace2.h" -#include "tvtime/plugins.h" - -#include - -GST_DEBUG_CATEGORY_STATIC (deinterlace2_debug); -#define GST_CAT_DEFAULT (deinterlace2_debug) - -/* Object signals and args */ -enum -{ - LAST_SIGNAL -}; - -/* Properties */ - -#define DEFAULT_MODE GST_DEINTERLACE2_MODE_INTERLACED -#define DEFAULT_METHOD GST_DEINTERLACE2_GREEDY_H -#define DEFAULT_FIELDS GST_DEINTERLACE2_ALL -#define DEFAULT_FIELD_LAYOUT GST_DEINTERLACE2_LAYOUT_AUTO - -enum -{ - PROP_0, - PROP_MODE, - PROP_METHOD, - PROP_FIELDS, - PROP_FIELD_LAYOUT, - PROP_LAST -}; - -G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT); - -static void -gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass) -{ - -} - -static void -gst_deinterlace_method_init (GstDeinterlaceMethod * self) -{ - -} - -static void -gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, GstBuffer * outbuf) -{ - GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self); - - klass->deinterlace_frame (self, parent, outbuf); -} - -static gint -gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self) -{ - GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self); - - return klass->fields_required; -} - -static gint -gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self) -{ - GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self); - - return klass->latency; -} - - -G_DEFINE_TYPE (GstDeinterlaceSimpleMethod, gst_deinterlace_simple_method, - GST_TYPE_DEINTERLACE_METHOD); - -static void -gst_deinterlace_simple_method_interpolate_scanline (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->m1, parent->row_stride); -} - -static void -gst_deinterlace_simple_method_copy_scanline (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->m0, parent->row_stride); -} - -static void -gst_deinterlace_simple_method_deinterlace_frame (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, GstBuffer * outbuf) -{ - GstDeinterlaceSimpleMethodClass *dsm_class = - GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self); - GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); - GstDeinterlaceScanlineData scanlines; - guint8 *out = GST_BUFFER_DATA (outbuf); - guint8 *field0 = NULL, *field1 = NULL, *field2 = NULL, *field3 = NULL; - gint cur_field_idx = parent->history_count - dm_class->fields_required; - guint cur_field_flags = parent->field_history[cur_field_idx].flags; - gint line; - - field0 = GST_BUFFER_DATA (parent->field_history[cur_field_idx].buf); - - g_assert (dm_class->fields_required <= 4); - - if (dm_class->fields_required >= 2) - field1 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 1].buf); - if (dm_class->fields_required >= 3) - field2 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 2].buf); - if (dm_class->fields_required >= 4) - field3 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 3].buf); - - - if (cur_field_flags == PICTURE_INTERLACED_BOTTOM) { - /* double the first scanline of the bottom field */ - oil_memcpy (out, field0, parent->row_stride); - out += parent->row_stride; - } - - oil_memcpy (out, field0, parent->row_stride); - out += parent->row_stride; - - for (line = 2; line <= parent->field_height; line++) { - - memset (&scanlines, 0, sizeof (scanlines)); - scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM); - - /* interp. scanline */ - scanlines.t0 = field0; - scanlines.b0 = field0 + parent->field_stride; - - if (field1 != NULL) { - scanlines.tt1 = field1; - scanlines.m1 = field1 + parent->field_stride; - scanlines.bb1 = field1 + parent->field_stride * 2; - field1 += parent->field_stride; - } - - if (field2 != NULL) { - scanlines.t2 = field2; - scanlines.b2 = field2 + parent->field_stride; - } - - if (field3 != NULL) { - scanlines.tt3 = field3; - scanlines.m3 = field3 + parent->field_stride; - scanlines.bb3 = field3 + parent->field_stride * 2; - field3 += parent->field_stride; - } - - /* set valid data for corner cases */ - if (line == 2) { - scanlines.tt1 = scanlines.bb1; - scanlines.tt3 = scanlines.bb3; - } else if (line == parent->field_height) { - scanlines.bb1 = scanlines.tt1; - scanlines.bb3 = scanlines.tt3; - } - - dsm_class->interpolate_scanline (self, parent, out, &scanlines, - parent->frame_width); - out += parent->row_stride; - - memset (&scanlines, 0, sizeof (scanlines)); - scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM); - - /* copy a scanline */ - scanlines.tt0 = field0; - scanlines.m0 = field0 + parent->field_stride; - scanlines.bb0 = field0 + parent->field_stride * 2; - field0 += parent->field_stride; - - if (field1 != NULL) { - scanlines.t1 = field1; - scanlines.b1 = field1 + parent->field_stride; - } - - if (field2 != NULL) { - scanlines.tt2 = field2; - scanlines.m2 = field2 + parent->field_stride; - scanlines.bb2 = field2 + parent->field_stride * 2; - field2 += parent->field_stride; - } - - if (field3 != NULL) { - scanlines.t3 = field3; - scanlines.b3 = field3 + parent->field_stride; - } - - /* set valid data for corner cases */ - if (line == parent->field_height) { - scanlines.bb0 = scanlines.tt0; - scanlines.b1 = scanlines.t1; - scanlines.bb2 = scanlines.tt2; - scanlines.b3 = scanlines.t3; - } - - dsm_class->copy_scanline (self, parent, out, &scanlines, - parent->frame_width); - out += parent->row_stride; - } - - if (cur_field_flags == PICTURE_INTERLACED_TOP) { - /* double the last scanline of the top field */ - oil_memcpy (out, field0, parent->row_stride); - } -} - -static void -gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass * - klass) -{ - GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass; - - dm_class->deinterlace_frame = gst_deinterlace_simple_method_deinterlace_frame; - dm_class->fields_required = 2; - - klass->interpolate_scanline = - gst_deinterlace_simple_method_interpolate_scanline; - klass->copy_scanline = gst_deinterlace_simple_method_copy_scanline; -} - -static void -gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self) -{ -} - -#define GST_TYPE_DEINTERLACE2_METHODS (gst_deinterlace2_methods_get_type ()) -static GType -gst_deinterlace2_methods_get_type (void) -{ - static GType deinterlace2_methods_type = 0; - - static const GEnumValue methods_types[] = { - {GST_DEINTERLACE2_TOMSMOCOMP, "Motion Adaptive: Motion Search", - "tomsmocomp"}, - {GST_DEINTERLACE2_GREEDY_H, "Motion Adaptive: Advanced Detection", - "greedyh"}, - {GST_DEINTERLACE2_GREEDY_L, "Motion Adaptive: Simple Detection", "greedyl"}, - {GST_DEINTERLACE2_VFIR, "Blur Vertical", "vfir"}, - {GST_DEINTERLACE2_LINEAR, "Television: Full resolution", "linear"}, - {GST_DEINTERLACE2_LINEAR_BLEND, "Blur: Temporal", "linearblend"}, - {GST_DEINTERLACE2_SCALER_BOB, "Double lines", "scalerbob"}, - {GST_DEINTERLACE2_WEAVE, "Weave", "weave"}, - {GST_DEINTERLACE2_WEAVE_TFF, "Progressive: Top Field First", "weavetff"}, - {GST_DEINTERLACE2_WEAVE_BFF, "Progressive: Bottom Field First", "weavebff"}, - {0, NULL, NULL}, - }; - - if (!deinterlace2_methods_type) { - deinterlace2_methods_type = - g_enum_register_static ("GstDeinterlace2Methods", methods_types); - } - return deinterlace2_methods_type; -} - -#define GST_TYPE_DEINTERLACE2_FIELDS (gst_deinterlace2_fields_get_type ()) -static GType -gst_deinterlace2_fields_get_type (void) -{ - static GType deinterlace2_fields_type = 0; - - static const GEnumValue fields_types[] = { - {GST_DEINTERLACE2_ALL, "All fields", "all"}, - {GST_DEINTERLACE2_TF, "Top fields only", "top"}, - {GST_DEINTERLACE2_BF, "Bottom fields only", "bottom"}, - {0, NULL, NULL}, - }; - - if (!deinterlace2_fields_type) { - deinterlace2_fields_type = - g_enum_register_static ("GstDeinterlace2Fields", fields_types); - } - return deinterlace2_fields_type; -} - -#define GST_TYPE_DEINTERLACE2_FIELD_LAYOUT (gst_deinterlace2_field_layout_get_type ()) -static GType -gst_deinterlace2_field_layout_get_type (void) -{ - static GType deinterlace2_field_layout_type = 0; - - static const GEnumValue field_layout_types[] = { - {GST_DEINTERLACE2_LAYOUT_AUTO, "Auto detection", "auto"}, - {GST_DEINTERLACE2_LAYOUT_TFF, "Top field first", "tff"}, - {GST_DEINTERLACE2_LAYOUT_BFF, "Bottom field first", "bff"}, - {0, NULL, NULL}, - }; - - if (!deinterlace2_field_layout_type) { - deinterlace2_field_layout_type = - g_enum_register_static ("GstDeinterlace2FieldLayout", - field_layout_types); - } - return deinterlace2_field_layout_type; -} - -#define GST_TYPE_DEINTERLACE2_MODES (gst_deinterlace2_modes_get_type ()) -static GType -gst_deinterlace2_modes_get_type (void) -{ - static GType deinterlace2_modes_type = 0; - - static const GEnumValue modes_types[] = { - {GST_DEINTERLACE2_MODE_AUTO, "Auto detection", "auto"}, - {GST_DEINTERLACE2_MODE_INTERLACED, "Enfore deinterlacing", "interlaced"}, - {GST_DEINTERLACE2_MODE_DISABLED, "Run in passthrough mode", "disabled"}, - {0, NULL, NULL}, - }; - - if (!deinterlace2_modes_type) { - deinterlace2_modes_type = - g_enum_register_static ("GstDeinterlace2Modes", modes_types); - } - return deinterlace2_modes_type; -} - -static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2") ";" - GST_VIDEO_CAPS_YUV ("YVYU")) - ); - -static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2") ";" - GST_VIDEO_CAPS_YUV ("YVYU")) - ); - -static void gst_deinterlace2_finalize (GObject * self); -static void gst_deinterlace2_set_property (GObject * self, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_deinterlace2_get_property (GObject * self, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstCaps *gst_deinterlace2_getcaps (GstPad * pad); -static gboolean gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_deinterlace2_sink_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_deinterlace2_chain (GstPad * pad, GstBuffer * buffer); -static GstStateChangeReturn gst_deinterlace2_change_state (GstElement * element, - GstStateChange transition); - -static gboolean gst_deinterlace2_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_deinterlace2_src_query (GstPad * pad, GstQuery * query); -static const GstQueryType *gst_deinterlace2_src_query_types (GstPad * pad); - -static void gst_deinterlace2_reset (GstDeinterlace2 * self); - -static void gst_deinterlace2_child_proxy_interface_init (gpointer g_iface, - gpointer iface_data); - -static void -_do_init (GType object_type) -{ - const GInterfaceInfo child_proxy_interface_info = { - (GInterfaceInitFunc) gst_deinterlace2_child_proxy_interface_init, - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY, - &child_proxy_interface_info); -} - -GST_BOILERPLATE_FULL (GstDeinterlace2, gst_deinterlace2, GstElement, - GST_TYPE_ELEMENT, _do_init); - -static void -gst_deinterlace2_set_method (GstDeinterlace2 * self, - GstDeinterlace2Methods method) -{ - - if (self->method) { - gst_child_proxy_child_removed (GST_OBJECT (self), - GST_OBJECT (self->method)); - gst_object_unparent (GST_OBJECT (self->method)); - self->method = NULL; - } - - switch (method) { - case GST_DEINTERLACE2_TOMSMOCOMP: - self->method = g_object_new (GST_TYPE_DEINTERLACE_TOMSMOCOMP, NULL); - break; - case GST_DEINTERLACE2_GREEDY_H: - self->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_H, NULL); - break; - case GST_DEINTERLACE2_GREEDY_L: - self->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_L, NULL); - break; - case GST_DEINTERLACE2_VFIR: - self->method = g_object_new (GST_TYPE_DEINTERLACE_VFIR, NULL); - break; - case GST_DEINTERLACE2_LINEAR: - self->method = g_object_new (GST_TYPE_DEINTERLACE_LINEAR, NULL); - break; - case GST_DEINTERLACE2_LINEAR_BLEND: - self->method = g_object_new (GST_TYPE_DEINTERLACE_LINEAR_BLEND, NULL); - break; - case GST_DEINTERLACE2_SCALER_BOB: - self->method = g_object_new (GST_TYPE_DEINTERLACE_SCALER_BOB, NULL); - break; - case GST_DEINTERLACE2_WEAVE: - self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE, NULL); - break; - case GST_DEINTERLACE2_WEAVE_TFF: - self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE_TFF, NULL); - break; - case GST_DEINTERLACE2_WEAVE_BFF: - self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE_BFF, NULL); - break; - default: - GST_WARNING_OBJECT (self, "Invalid Deinterlacer Method"); - return; - } - - self->method_id = method; - - gst_object_set_name (GST_OBJECT (self->method), "method"); - gst_object_set_parent (GST_OBJECT (self->method), GST_OBJECT (self)); - gst_child_proxy_child_added (GST_OBJECT (self), GST_OBJECT (self->method)); -} - -static void -gst_deinterlace2_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_templ)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_templ)); - - gst_element_class_set_details_simple (element_class, - "Deinterlacer", - "Filter/Video", - "Deinterlace Methods ported from DScaler/TvTime", - "Martin Eikermann , " - "Sebastian Dröge "); -} - -static void -gst_deinterlace2_class_init (GstDeinterlace2Class * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - GstElementClass *element_class = (GstElementClass *) klass; - - gobject_class->set_property = gst_deinterlace2_set_property; - gobject_class->get_property = gst_deinterlace2_get_property; - gobject_class->finalize = gst_deinterlace2_finalize; - - /** - * GstDeinterlace2:mode - * - * This selects whether the deinterlacing methods should - * always be applied or if they should only be applied - * on content that has the "interlaced" flag on the caps. - * - */ - g_object_class_install_property (gobject_class, PROP_MODE, - g_param_spec_enum ("mode", - "Mode", - "Deinterlace Mode", - GST_TYPE_DEINTERLACE2_MODES, - DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - /** - * GstDeinterlace2:method - * - * Selects the different deinterlacing algorithms that can be used. - * These provide different quality and CPU usage. - * - * Some methods provide parameters which can be set by getting - * the "method" child via the #GstChildProxy interface and - * setting the appropiate properties on it. - * - * - * - * - * tomsmocomp - * Motion Adaptive: Motion Search - * - * - * - * - * greedyh - * Motion Adaptive: Advanced Detection - * - * - * - * - * greedyl - * Motion Adaptive: Simple Detection - * - * - * - * - * vfir - * Blur vertical - * - * - * - * - * linear - * Linear interpolation - * - * - * - * - * linearblend - * Linear interpolation in time domain - * - * - * - * - * scalerbob - * Double lines - * - * - * - * - * weave - * Weave - * - * - * - * - * weavetff - * Progressive: Top Field First - * - * - * - * - * weavebff - * Progressive: Bottom Field First - * - * - * - */ - g_object_class_install_property (gobject_class, PROP_METHOD, - g_param_spec_enum ("method", - "Method", - "Deinterlace Method", - GST_TYPE_DEINTERLACE2_METHODS, - DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - /** - * GstDeinterlace2:fields - * - * This selects which fields should be output. If "all" is selected - * the output framerate will be double. - * - */ - g_object_class_install_property (gobject_class, PROP_FIELDS, - g_param_spec_enum ("fields", - "fields", - "Fields to use for deinterlacing", - GST_TYPE_DEINTERLACE2_FIELDS, - DEFAULT_FIELDS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - /** - * GstDeinterlace2:layout - * - * This selects which fields is the first in time. - * - */ - g_object_class_install_property (gobject_class, PROP_FIELD_LAYOUT, - g_param_spec_enum ("tff", - "tff", - "Deinterlace top field first", - GST_TYPE_DEINTERLACE2_FIELD_LAYOUT, - DEFAULT_FIELD_LAYOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - element_class->change_state = - GST_DEBUG_FUNCPTR (gst_deinterlace2_change_state); -} - -static GstObject * -gst_deinterlace2_child_proxy_get_child_by_index (GstChildProxy * child_proxy, - guint index) -{ - GstDeinterlace2 *self = GST_DEINTERLACE2 (child_proxy); - - g_return_val_if_fail (index == 0, NULL); - - return gst_object_ref (self->method); -} - -static guint -gst_deinterlace2_child_proxy_get_children_count (GstChildProxy * child_proxy) -{ - return 1; -} - -static void -gst_deinterlace2_child_proxy_interface_init (gpointer g_iface, - gpointer iface_data) -{ - GstChildProxyInterface *iface = g_iface; - - iface->get_child_by_index = gst_deinterlace2_child_proxy_get_child_by_index; - iface->get_children_count = gst_deinterlace2_child_proxy_get_children_count; -} - -static void -gst_deinterlace2_init (GstDeinterlace2 * self, GstDeinterlace2Class * klass) -{ - self->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); - gst_pad_set_chain_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_chain)); - gst_pad_set_event_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_sink_event)); - gst_pad_set_setcaps_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_setcaps)); - gst_pad_set_getcaps_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_getcaps)); - gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); - - self->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); - gst_pad_set_event_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_src_event)); - gst_pad_set_query_type_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_src_query_types)); - gst_pad_set_query_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_src_query)); - gst_pad_set_setcaps_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_setcaps)); - gst_pad_set_getcaps_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_deinterlace2_getcaps)); - gst_element_add_pad (GST_ELEMENT (self), self->srcpad); - - gst_element_no_more_pads (GST_ELEMENT (self)); - - self->mode = DEFAULT_MODE; - gst_deinterlace2_set_method (self, DEFAULT_METHOD); - self->fields = DEFAULT_FIELDS; - self->field_layout = DEFAULT_FIELD_LAYOUT; - - gst_deinterlace2_reset (self); -} - -static void -gst_deinterlace2_reset_history (GstDeinterlace2 * self) -{ - gint i; - - for (i = 0; i < self->history_count; i++) { - if (self->field_history[i].buf) { - gst_buffer_unref (self->field_history[i].buf); - self->field_history[i].buf = NULL; - } - } - memset (self->field_history, 0, MAX_FIELD_HISTORY * sizeof (GstPicture)); - self->history_count = 0; -} - -static void -gst_deinterlace2_reset (GstDeinterlace2 * self) -{ - self->row_stride = 0; - self->frame_width = 0; - self->frame_height = 0; - self->frame_rate_n = 0; - self->frame_rate_d = 0; - self->field_height = 0; - self->field_stride = 0; - - gst_deinterlace2_reset_history (self); -} - -static void -gst_deinterlace2_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstDeinterlace2 *self; - - g_return_if_fail (GST_IS_DEINTERLACE2 (object)); - self = GST_DEINTERLACE2 (object); - - switch (prop_id) { - case PROP_MODE:{ - gint oldmode; - - GST_OBJECT_LOCK (self); - oldmode = self->mode; - self->mode = g_value_get_enum (value); - if (self->mode != oldmode && GST_PAD_CAPS (self->srcpad)) - gst_deinterlace2_setcaps (self->sinkpad, GST_PAD_CAPS (self->sinkpad)); - GST_OBJECT_UNLOCK (self); - break; - } - case PROP_METHOD: - gst_deinterlace2_set_method (self, g_value_get_enum (value)); - break; - case PROP_FIELDS:{ - gint oldfields; - - GST_OBJECT_LOCK (self); - oldfields = self->fields; - self->fields = g_value_get_enum (value); - if (self->fields != oldfields && GST_PAD_CAPS (self->srcpad)) - gst_deinterlace2_setcaps (self->sinkpad, GST_PAD_CAPS (self->sinkpad)); - GST_OBJECT_UNLOCK (self); - break; - } - case PROP_FIELD_LAYOUT: - self->field_layout = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); - } - -} - -static void -gst_deinterlace2_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstDeinterlace2 *self; - - g_return_if_fail (GST_IS_DEINTERLACE2 (object)); - self = GST_DEINTERLACE2 (object); - - switch (prop_id) { - case PROP_MODE: - g_value_set_enum (value, self->mode); - break; - case PROP_METHOD: - g_value_set_enum (value, self->method_id); - break; - case PROP_FIELDS: - g_value_set_enum (value, self->fields); - break; - case PROP_FIELD_LAYOUT: - g_value_set_enum (value, self->field_layout); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); - } -} - -static void -gst_deinterlace2_finalize (GObject * object) -{ - GstDeinterlace2 *self = GST_DEINTERLACE2 (object); - - gst_deinterlace2_reset (self); - - if (self->method) { - gst_object_unparent (GST_OBJECT (self->method)); - self->method = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static GstBuffer * -gst_deinterlace2_pop_history (GstDeinterlace2 * self) -{ - GstBuffer *buffer = NULL; - - g_assert (self->history_count > 0); - - buffer = self->field_history[self->history_count - 1].buf; - - self->history_count--; - GST_DEBUG_OBJECT (self, "pop, size(history): %d", self->history_count); - - return buffer; -} - -#if 0 -static GstBuffer * -gst_deinterlace2_head_history (GstDeinterlace2 * self) -{ - return self->field_history[self->history_count - 1].buf; -} -#endif - - -/* invariant: field with smallest timestamp is self->field_history[self->history_count-1] - -*/ - -static void -gst_deinterlace2_push_history (GstDeinterlace2 * self, GstBuffer * buffer) -{ - int i = 1; - GstClockTime timestamp; - GstDeinterlace2FieldLayout field_layout = self->field_layout; - gboolean repeated = GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_RFF); - gboolean tff = GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_TFF); - gboolean onefield = - GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_ONEFIELD); - GstBuffer *field1, *field2; - guint fields_to_push = (onefield) ? 1 : (!repeated) ? 2 : 3; - gint field1_flags, field2_flags; - - g_assert (self->history_count < MAX_FIELD_HISTORY - fields_to_push); - - for (i = MAX_FIELD_HISTORY - 1; i >= fields_to_push; i--) { - self->field_history[i].buf = self->field_history[i - fields_to_push].buf; - self->field_history[i].flags = - self->field_history[i - fields_to_push].flags; - } - - if (field_layout == GST_DEINTERLACE2_LAYOUT_AUTO) { - if (!self->interlaced) { - GST_WARNING_OBJECT (self, "Can't detect field layout -- assuming TFF"); - field_layout = GST_DEINTERLACE2_LAYOUT_TFF; - } else if (tff) { - field_layout = GST_DEINTERLACE2_LAYOUT_TFF; - } else { - field_layout = GST_DEINTERLACE2_LAYOUT_BFF; - } - } - - if (field_layout == GST_DEINTERLACE2_LAYOUT_TFF) { - GST_DEBUG_OBJECT (self, "Top field first"); - field1 = gst_buffer_ref (buffer); - field1_flags = PICTURE_INTERLACED_TOP; - field2 = gst_buffer_create_sub (buffer, self->row_stride, - GST_BUFFER_SIZE (buffer) - self->row_stride); - field2_flags = PICTURE_INTERLACED_BOTTOM; - } else { - GST_DEBUG_OBJECT (self, "Bottom field first"); - field1 = gst_buffer_create_sub (buffer, self->row_stride, - GST_BUFFER_SIZE (buffer) - self->row_stride); - field1_flags = PICTURE_INTERLACED_BOTTOM; - field2 = gst_buffer_ref (buffer); - field2_flags = PICTURE_INTERLACED_TOP; - } - - /* Timestamps are assigned to the field buffers under the assumption that - the timestamp of the buffer equals the first fields timestamp */ - - timestamp = GST_BUFFER_TIMESTAMP (buffer); - GST_BUFFER_TIMESTAMP (field1) = timestamp; - GST_BUFFER_TIMESTAMP (field2) = timestamp + self->field_duration; - if (repeated) - GST_BUFFER_TIMESTAMP (field2) += self->field_duration; - - if (repeated) { - self->field_history[0].buf = field2; - self->field_history[0].flags = field2_flags; - self->field_history[1].buf = gst_buffer_ref (field1); - GST_BUFFER_TIMESTAMP (self->field_history[1].buf) += self->field_duration; - self->field_history[1].flags = field1_flags; - self->field_history[2].buf = field1; - self->field_history[2].flags = field1_flags; - } else if (!onefield) { - self->field_history[0].buf = field2; - self->field_history[0].flags = field2_flags; - self->field_history[1].buf = field1; - self->field_history[1].flags = field1_flags; - } else { /* onefield */ - self->field_history[0].buf = field1; - self->field_history[0].flags = field1_flags; - gst_buffer_unref (field2); - } - - self->history_count += fields_to_push; - GST_DEBUG_OBJECT (self, "push, size(history): %d", self->history_count); - - gst_buffer_unref (buffer); -} - -static GstFlowReturn -gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf) -{ - GstDeinterlace2 *self = NULL; - GstClockTime timestamp; - GstFlowReturn ret = GST_FLOW_OK; - gint fields_required = 0; - gint cur_field_idx = 0; - GstBuffer *outbuf; - - self = GST_DEINTERLACE2 (GST_PAD_PARENT (pad)); - - if (self->mode == GST_DEINTERLACE2_MODE_DISABLED || (!self->interlaced - && self->mode != GST_DEINTERLACE2_MODE_INTERLACED)) - return gst_pad_push (self->srcpad, buf); - - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { - GST_DEBUG_OBJECT (self, "DISCONT buffer, resetting history"); - gst_deinterlace2_reset_history (self); - } - - gst_deinterlace2_push_history (self, buf); - buf = NULL; - - fields_required = gst_deinterlace_method_get_fields_required (self->method); - - /* Not enough fields in the history */ - if (self->history_count < fields_required + 1) { - /* TODO: do bob or just forward frame */ - GST_DEBUG_OBJECT (self, "HistoryCount=%d", self->history_count); - return GST_FLOW_OK; - } - - while (self->history_count >= fields_required) { - if (self->fields == GST_DEINTERLACE2_ALL) - GST_DEBUG_OBJECT (self, "All fields"); - if (self->fields == GST_DEINTERLACE2_TF) - GST_DEBUG_OBJECT (self, "Top fields"); - if (self->fields == GST_DEINTERLACE2_BF) - GST_DEBUG_OBJECT (self, "Bottom fields"); - - cur_field_idx = self->history_count - fields_required; - - if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP - && self->fields == GST_DEINTERLACE2_TF) || - self->fields == GST_DEINTERLACE2_ALL) { - GST_DEBUG_OBJECT (self, "deinterlacing top field"); - - /* create new buffer */ - ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad, - GST_BUFFER_OFFSET_NONE, self->frame_size, - GST_PAD_CAPS (self->srcpad), &outbuf); - if (ret != GST_FLOW_OK) - return ret; - - /* do magic calculus */ - gst_deinterlace_method_deinterlace_frame (self->method, self, outbuf); - - g_assert (self->history_count - 1 - - gst_deinterlace_method_get_latency (self->method) >= 0); - buf = - self->field_history[self->history_count - 1 - - gst_deinterlace_method_get_latency (self->method)].buf; - timestamp = GST_BUFFER_TIMESTAMP (buf); - - gst_buffer_unref (gst_deinterlace2_pop_history (self)); - - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - if (self->fields == GST_DEINTERLACE2_ALL) - GST_BUFFER_DURATION (outbuf) = self->field_duration; - else - GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration; - - ret = gst_pad_push (self->srcpad, outbuf); - outbuf = NULL; - if (ret != GST_FLOW_OK) - return ret; - } - /* no calculation done: remove excess field */ - else if (self->field_history[cur_field_idx].flags == - PICTURE_INTERLACED_TOP && self->fields == GST_DEINTERLACE2_BF) { - GST_DEBUG_OBJECT (self, "Removing unused top field"); - gst_buffer_unref (gst_deinterlace2_pop_history (self)); - } - - cur_field_idx = self->history_count - fields_required; - if (self->history_count < fields_required) - break; - - /* deinterlace bottom_field */ - if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM - && self->fields == GST_DEINTERLACE2_BF) || - self->fields == GST_DEINTERLACE2_ALL) { - GST_DEBUG_OBJECT (self, "deinterlacing bottom field"); - - /* create new buffer */ - ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad, - GST_BUFFER_OFFSET_NONE, self->frame_size, - GST_PAD_CAPS (self->srcpad), &outbuf); - if (ret != GST_FLOW_OK) - return ret; - - /* do magic calculus */ - gst_deinterlace_method_deinterlace_frame (self->method, self, outbuf); - - g_assert (self->history_count - 1 - - gst_deinterlace_method_get_latency (self->method) >= 0); - buf = - self->field_history[self->history_count - 1 - - gst_deinterlace_method_get_latency (self->method)].buf; - timestamp = GST_BUFFER_TIMESTAMP (buf); - - gst_buffer_unref (gst_deinterlace2_pop_history (self)); - - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - if (self->fields == GST_DEINTERLACE2_ALL) - GST_BUFFER_DURATION (outbuf) = self->field_duration; - else - GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration; - - ret = gst_pad_push (self->srcpad, outbuf); - outbuf = NULL; - - if (ret != GST_FLOW_OK) - return ret; - } - /* no calculation done: remove excess field */ - else if (self->field_history[cur_field_idx].flags == - PICTURE_INTERLACED_BOTTOM && self->fields == GST_DEINTERLACE2_TF) { - GST_DEBUG_OBJECT (self, "Removing unused bottom field"); - gst_buffer_unref (gst_deinterlace2_pop_history (self)); - } - } - - GST_DEBUG_OBJECT (self, "----chain end ----\n\n"); - - return ret; -} - -static gint -gst_greatest_common_divisor (gint a, gint b) -{ - while (b != 0) { - int temp = a; - - a = b; - b = temp % b; - } - - return ABS (a); -} - -static gboolean -gst_fraction_double (gint * n_out, gint * d_out, gboolean half) -{ - gint n, d, gcd; - - n = *n_out; - d = *d_out; - - if (d == 0) - return FALSE; - - if (n == 0 || (n == G_MAXINT && d == 1)) - return TRUE; - - gcd = gst_greatest_common_divisor (n, d); - n /= gcd; - d /= gcd; - - if (!half) { - if (G_MAXINT / 2 >= ABS (n)) { - n *= 2; - } else if (d >= 2) { - d /= 2; - } else { - return FALSE; - } - } else { - if (G_MAXINT / 2 >= ABS (d)) { - d *= 2; - } else if (n >= 2) { - n /= 2; - } else { - return FALSE; - } - } - - *n_out = n; - *d_out = d; - - return TRUE; -} - -static GstCaps * -gst_deinterlace2_getcaps (GstPad * pad) -{ - GstCaps *ret; - GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); - GstPad *otherpad; - gint len; - const GstCaps *ourcaps; - GstCaps *peercaps; - - GST_OBJECT_LOCK (self); - - otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; - - ourcaps = gst_pad_get_pad_template_caps (pad); - peercaps = gst_pad_peer_get_caps (otherpad); - - if (peercaps) { - ret = gst_caps_intersect (ourcaps, peercaps); - gst_caps_unref (peercaps); - } else { - ret = gst_caps_copy (ourcaps); - } - - GST_OBJECT_UNLOCK (self); - - if ((self->interlaced || self->mode == GST_DEINTERLACE2_MODE_INTERLACED) && - self->fields == GST_DEINTERLACE2_ALL - && self->mode != GST_DEINTERLACE2_MODE_DISABLED) { - for (len = gst_caps_get_size (ret); len > 0; len--) { - GstStructure *s = gst_caps_get_structure (ret, len - 1); - const GValue *val; - - val = gst_structure_get_value (s, "framerate"); - if (!val) - continue; - - if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) { - gint n, d; - - n = gst_value_get_fraction_numerator (val); - d = gst_value_get_fraction_denominator (val); - - if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { - goto error; - } - - gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL); - } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) { - const GValue *min, *max; - GValue nrange = { 0, }, nmin = { - 0,}, nmax = { - 0,}; - gint n, d; - - g_value_init (&nrange, GST_TYPE_FRACTION_RANGE); - g_value_init (&nmin, GST_TYPE_FRACTION); - g_value_init (&nmax, GST_TYPE_FRACTION); - - min = gst_value_get_fraction_range_min (val); - max = gst_value_get_fraction_range_max (val); - - n = gst_value_get_fraction_numerator (min); - d = gst_value_get_fraction_denominator (min); - - if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { - g_value_unset (&nrange); - g_value_unset (&nmax); - g_value_unset (&nmin); - goto error; - } - - gst_value_set_fraction (&nmin, n, d); - - n = gst_value_get_fraction_numerator (max); - d = gst_value_get_fraction_denominator (max); - - if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { - g_value_unset (&nrange); - g_value_unset (&nmax); - g_value_unset (&nmin); - goto error; - } - - gst_value_set_fraction (&nmax, n, d); - gst_value_set_fraction_range (&nrange, &nmin, &nmax); - - gst_structure_set_value (s, "framerate", &nrange); - - g_value_unset (&nmin); - g_value_unset (&nmax); - g_value_unset (&nrange); - } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { - const GValue *lval; - GValue nlist = { 0, }; - GValue nval = { 0, }; - gint i; - - g_value_init (&nlist, GST_TYPE_LIST); - for (i = gst_value_list_get_size (val); i > 0; i--) { - gint n, d; - - lval = gst_value_list_get_value (val, i); - - if (G_VALUE_TYPE (lval) != GST_TYPE_FRACTION) - continue; - - n = gst_value_get_fraction_numerator (lval); - d = gst_value_get_fraction_denominator (lval); - - /* Double/Half the framerate but if this fails simply - * skip this value from the list */ - if (!gst_fraction_double (&n, &d, pad != self->srcpad)) { - continue; - } - - g_value_init (&nval, GST_TYPE_FRACTION); - - gst_value_set_fraction (&nval, n, d); - gst_value_list_append_value (&nlist, &nval); - g_value_unset (&nval); - } - gst_structure_set_value (s, "framerate", &nlist); - g_value_unset (&nlist); - } - } - } - - GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret); - - return ret; - -error: - GST_ERROR_OBJECT (pad, "Unable to transform peer caps"); - gst_caps_unref (ret); - return NULL; -} - -static gboolean -gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps) -{ - gboolean res = TRUE; - GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); - GstPad *otherpad; - GstStructure *structure; - GstVideoFormat fmt; - guint32 fourcc; - GstCaps *othercaps; - - otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; - - structure = gst_caps_get_structure (caps, 0); - - res = gst_structure_get_int (structure, "width", &self->frame_width); - res &= gst_structure_get_int (structure, "height", &self->frame_height); - res &= - gst_structure_get_fraction (structure, "framerate", &self->frame_rate_n, - &self->frame_rate_d); - res &= gst_structure_get_fourcc (structure, "format", &fourcc); - res &= gst_video_format_parse_caps_interlaced (caps, &self->interlaced); - if (!res) - goto invalid_caps; - - if ((self->interlaced || self->mode == GST_DEINTERLACE2_MODE_INTERLACED) && - self->fields == GST_DEINTERLACE2_ALL - && self->mode != GST_DEINTERLACE2_MODE_DISABLED) { - gint fps_n = self->frame_rate_n, fps_d = self->frame_rate_d; - - if (!gst_fraction_double (&fps_n, &fps_d, otherpad != self->srcpad)) - goto invalid_caps; - - othercaps = gst_caps_copy (caps); - - gst_caps_set_simple (othercaps, "framerate", GST_TYPE_FRACTION, fps_n, - fps_d, NULL); - } else { - othercaps = gst_caps_ref (caps); - } - - if (!gst_pad_set_caps (otherpad, othercaps)) - goto caps_not_accepted; - gst_caps_unref (othercaps); - - self->field_height = self->frame_height / 2; - - fmt = gst_video_format_from_fourcc (fourcc); - - /* TODO: only true if fields are subbuffers of interlaced frames, - change when the buffer-fields concept has landed */ - self->field_stride = - gst_video_format_get_row_stride (fmt, 0, self->frame_width) * 2; - - /* in bytes */ - self->row_stride = - gst_video_format_get_row_stride (fmt, 0, self->frame_width); - self->frame_size = - gst_video_format_get_size (fmt, self->frame_width, self->frame_height); - - if (self->fields == GST_DEINTERLACE2_ALL && otherpad == self->srcpad) - self->field_duration = - gst_util_uint64_scale (GST_SECOND, self->frame_rate_d, - self->frame_rate_n); - else - self->field_duration = - gst_util_uint64_scale (GST_SECOND, self->frame_rate_d, - 2 * self->frame_rate_n); - - GST_DEBUG_OBJECT (self, "Set caps: %" GST_PTR_FORMAT, caps); - -done: - - gst_object_unref (self); - return res; - -invalid_caps: - res = FALSE; - GST_ERROR_OBJECT (pad, "Invalid caps: %" GST_PTR_FORMAT, caps); - goto done; - -caps_not_accepted: - res = FALSE; - GST_ERROR_OBJECT (pad, "Caps not accepted: %" GST_PTR_FORMAT, othercaps); - gst_caps_unref (othercaps); - goto done; -} - -static gboolean -gst_deinterlace2_sink_event (GstPad * pad, GstEvent * event) -{ - gboolean res = TRUE; - GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); - - GST_LOG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - case GST_EVENT_EOS: - case GST_EVENT_NEWSEGMENT: - gst_deinterlace2_reset_history (self); - - /* fall through */ - default: - res = gst_pad_event_default (pad, event); - break; - } - - gst_object_unref (self); - return res; -} - -static GstStateChangeReturn -gst_deinterlace2_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret; - GstDeinterlace2 *self = GST_DEINTERLACE2 (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret != GST_STATE_CHANGE_SUCCESS) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_deinterlace2_reset (self); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - default: - break; - } - - return ret; -} - -static gboolean -gst_deinterlace2_src_event (GstPad * pad, GstEvent * event) -{ - GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); - gboolean res; - - GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - default: - res = gst_pad_event_default (pad, event); - break; - } - - gst_object_unref (self); - - return res; -} - -static gboolean -gst_deinterlace2_src_query (GstPad * pad, GstQuery * query) -{ - GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); - gboolean res = FALSE; - - GST_LOG_OBJECT (self, "%s query", GST_QUERY_TYPE_NAME (query)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_LATENCY: - if ((self->interlaced || self->mode == GST_DEINTERLACE2_MODE_INTERLACED) - && self->mode != GST_DEINTERLACE2_MODE_DISABLED) { - GstClockTime min, max; - gboolean live; - GstPad *peer; - - if ((peer = gst_pad_get_peer (self->sinkpad))) { - if ((res = gst_pad_query (peer, query))) { - GstClockTime latency; - gint fields_required = 0; - gint method_latency = 0; - - if (self->method) { - fields_required = - gst_deinterlace_method_get_fields_required (self->method); - method_latency = - gst_deinterlace_method_get_latency (self->method); - } - - gst_query_parse_latency (query, &live, &min, &max); - - GST_DEBUG_OBJECT (self, "Peer latency: min %" - GST_TIME_FORMAT " max %" GST_TIME_FORMAT, - GST_TIME_ARGS (min), GST_TIME_ARGS (max)); - - /* add our own latency */ - latency = (fields_required + method_latency) * self->field_duration; - - GST_DEBUG_OBJECT (self, "Our latency: min %" GST_TIME_FORMAT - ", max %" GST_TIME_FORMAT, - GST_TIME_ARGS (latency), GST_TIME_ARGS (latency)); - - min += latency; - if (max != GST_CLOCK_TIME_NONE) - max += latency; - else - max = latency; - - GST_DEBUG_OBJECT (self, "Calculated total latency : min %" - GST_TIME_FORMAT " max %" GST_TIME_FORMAT, - GST_TIME_ARGS (min), GST_TIME_ARGS (max)); - - gst_query_set_latency (query, live, min, max); - } - gst_object_unref (peer); - } else { - res = gst_pad_query_default (pad, query); - } - break; - } - default: - res = gst_pad_query_default (pad, query); - break; - } - - gst_object_unref (self); - return res; -} - -static const GstQueryType * -gst_deinterlace2_src_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_LATENCY, - GST_QUERY_NONE - }; - return types; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - GST_DEBUG_CATEGORY_INIT (deinterlace2_debug, "deinterlace2", 0, - "Deinterlacer"); - - oil_init (); - - if (!gst_element_register (plugin, "deinterlace2", GST_RANK_NONE, - GST_TYPE_DEINTERLACE2)) { - return FALSE; - } - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "deinterlace2", - "Deinterlacer", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, - GST_PACKAGE_ORIGIN); diff --git a/gst/deinterlace2/gstdeinterlace2.h b/gst/deinterlace2/gstdeinterlace2.h deleted file mode 100644 index 7a08d411..00000000 --- a/gst/deinterlace2/gstdeinterlace2.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2005 Martin Eikermann - * Copyright (C) 2008-2009 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_DEINTERLACE_2_H__ -#define __GST_DEINTERLACE_2_H__ - -#include -#include -#include -#include -#include - -#ifdef HAVE_GCC_ASM -#if defined(HAVE_CPU_I386) || defined(HAVE_CPU_X86_64) -#define BUILD_X86_ASM -#endif -#endif - -G_BEGIN_DECLS - -#define GST_TYPE_DEINTERLACE2 \ - (gst_deinterlace2_get_type()) -#define GST_DEINTERLACE2(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEINTERLACE2,GstDeinterlace2)) -#define GST_DEINTERLACE2_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEINTERLACE2,GstDeinterlace2)) -#define GST_IS_DEINTERLACE2(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEINTERLACE2)) -#define GST_IS_DEINTERLACE2_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEINTERLACE2)) - -typedef struct _GstDeinterlace2 GstDeinterlace2; -typedef struct _GstDeinterlace2Class GstDeinterlace2Class; - -#define GST_TYPE_DEINTERLACE_METHOD (gst_deinterlace_method_get_type ()) -#define GST_IS_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD)) -#define GST_IS_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD)) -#define GST_DEINTERLACE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass)) -#define GST_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethod)) -#define GST_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass)) -#define GST_DEINTERLACE_METHOD_CAST(obj) ((GstDeinterlaceMethod*)(obj)) - -typedef struct _GstDeinterlaceMethod GstDeinterlaceMethod; -typedef struct _GstDeinterlaceMethodClass GstDeinterlaceMethodClass; - -/* - * This structure defines the deinterlacer plugin. - */ - -struct _GstDeinterlaceMethod { - GstObject parent; -}; - -struct _GstDeinterlaceMethodClass { - GstObjectClass parent_class; - guint fields_required; - guint latency; - - void (*deinterlace_frame) (GstDeinterlaceMethod *self, GstDeinterlace2 * parent, GstBuffer *outbuf); - - const gchar *name; - const gchar *nick; -}; - -GType gst_deinterlace_method_get_type (void); - -#define GST_TYPE_DEINTERLACE_SIMPLE_METHOD (gst_deinterlace_simple_method_get_type ()) -#define GST_IS_DEINTERLACE_SIMPLE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD)) -#define GST_IS_DEINTERLACE_SIMPLE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_SIMPLE_METHOD)) -#define GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethodClass)) -#define GST_DEINTERLACE_SIMPLE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethod)) -#define GST_DEINTERLACE_SIMPLE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethodClass)) -#define GST_DEINTERLACE_SIMPLE_METHOD_CAST(obj) ((GstDeinterlaceSimpleMethod*)(obj)) - -typedef struct _GstDeinterlaceSimpleMethod GstDeinterlaceSimpleMethod; -typedef struct _GstDeinterlaceSimpleMethodClass GstDeinterlaceSimpleMethodClass; -typedef struct _GstDeinterlaceScanlineData GstDeinterlaceScanlineData; - -/* - * This structure defines the simple deinterlacer plugin. - */ - -struct _GstDeinterlaceScanlineData { - guint8 *tt0, *t0, *m0, *b0, *bb0; - guint8 *tt1, *t1, *m1, *b1, *bb1; - guint8 *tt2, *t2, *m2, *b2, *bb2; - guint8 *tt3, *t3, *m3, *b3, *bb3; - gboolean bottom_field; -}; - -/** - * For interpolate_scanline the input is: - * - * | t-3 t-2 t-1 t - * | Field 3 | Field 2 | Field 1 | Field 0 | - * | TT3 | | TT1 | | - * | | T2 | | T0 | - * | M3 | | M1 | | - * | | B2 | | B0 | - * | BB3 | | BB1 | | - * - * For copy_scanline the input is: - * - * | t-3 t-2 t-1 t - * | Field 3 | Field 2 | Field 1 | Field 0 | - * | | TT2 | | TT0 | - * | T3 | | T1 | | - * | | M2 | | M0 | - * | B3 | | B1 | | - * | | BB2 | | BB0 | - * - * All other values are NULL. - */ - -struct _GstDeinterlaceSimpleMethod { - GstDeinterlaceMethod parent; -}; - -struct _GstDeinterlaceSimpleMethodClass { - GstDeinterlaceMethodClass parent_class; - - void (*interpolate_scanline) (GstDeinterlaceMethod *self, GstDeinterlace2 * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width); - void (*copy_scanline) (GstDeinterlaceMethod *self, GstDeinterlace2 * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width); -}; - -GType gst_deinterlace_simple_method_get_type (void); - - -#define MAX_FIELD_HISTORY 10 - -#define PICTURE_PROGRESSIVE 0 -#define PICTURE_INTERLACED_BOTTOM 1 -#define PICTURE_INTERLACED_TOP 2 -#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP) - -typedef struct -{ - /* pointer to the start of data for this field */ - GstBuffer *buf; - /* see PICTURE_ flags */ - guint flags; -} GstPicture; - -typedef enum -{ - GST_DEINTERLACE2_TOMSMOCOMP, - GST_DEINTERLACE2_GREEDY_H, - GST_DEINTERLACE2_GREEDY_L, - GST_DEINTERLACE2_VFIR, - GST_DEINTERLACE2_LINEAR, - GST_DEINTERLACE2_LINEAR_BLEND, - GST_DEINTERLACE2_SCALER_BOB, - GST_DEINTERLACE2_WEAVE, - GST_DEINTERLACE2_WEAVE_TFF, - GST_DEINTERLACE2_WEAVE_BFF -} GstDeinterlace2Methods; - -typedef enum -{ - GST_DEINTERLACE2_ALL, /* All (missing data is interp.) */ - GST_DEINTERLACE2_TF, /* Top Fields Only */ - GST_DEINTERLACE2_BF /* Bottom Fields Only */ -} GstDeinterlace2Fields; - -typedef enum -{ - GST_DEINTERLACE2_LAYOUT_AUTO, - GST_DEINTERLACE2_LAYOUT_TFF, - GST_DEINTERLACE2_LAYOUT_BFF -} GstDeinterlace2FieldLayout; - -typedef enum { - GST_DEINTERLACE2_MODE_AUTO, - GST_DEINTERLACE2_MODE_INTERLACED, - GST_DEINTERLACE2_MODE_DISABLED -} GstDeinterlace2Mode; - -struct _GstDeinterlace2 -{ - GstElement parent; - - GstPad *srcpad, *sinkpad; - - /* */ - - GstDeinterlace2Mode mode; - - GstDeinterlace2FieldLayout field_layout; - - guint frame_size; - gint frame_rate_n, frame_rate_d; - gboolean interlaced; - - /* Duration of one field */ - GstClockTime field_duration; - - GstDeinterlace2Fields fields; - - GstDeinterlace2Methods method_id; - GstDeinterlaceMethod *method; - - /* The most recent pictures - PictureHistory[0] is always the most recent. - Pointers are NULL if the picture in question isn't valid, e.g. because - the program just started or a picture was skipped. - */ - GstPicture field_history[MAX_FIELD_HISTORY]; - guint history_count; - - /* Number of bytes of actual data in each scanline. May be less than - OverlayPitch since the overlay's scanlines might have alignment - requirements. Generally equal to FrameWidth * 2. - */ - guint row_stride; - - /* Number of pixels in each scanline. */ - gint frame_width; - - /* Number of scanlines per frame. */ - gint frame_height; - - /* Number of scanlines per field. FrameHeight / 2, mostly for - cleanliness so we don't have to keep dividing FrameHeight by 2. - */ - gint field_height; - - /* distance between lines in image - need not match the pixel width - */ - guint field_stride; -}; - -struct _GstDeinterlace2Class -{ - GstElementClass parent_class; -}; - -GType gst_deinterlace2_get_type (void); - -G_END_DECLS -#endif /* __GST_DEINTERLACE_2_H__ */ diff --git a/gst/deinterlace2/tvtime/greedy.c b/gst/deinterlace2/tvtime/greedy.c deleted file mode 100644 index 7d4e4b3a..00000000 --- a/gst/deinterlace2/tvtime/greedy.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * - * GStreamer - * Copyright (c) 2000 Tom Barry All rights reserved. - * mmx.h port copyright (c) 2002 Billy Biggs . - * - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Relicensed for GStreamer from GPL to LGPL with permit from Tom Barry - * and Billy Biggs. - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" - -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L)) -#define GST_IS_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L)) -#define GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass)) -#define GST_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyL)) -#define GST_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass)) -#define GST_DEINTERLACE_METHOD_GREEDY_L_CAST(obj) ((GstDeinterlaceMethodGreedyL*)(obj)) - -GType gst_deinterlace_method_greedy_l_get_type (void); - -typedef struct -{ - GstDeinterlaceMethod parent; - - guint max_comb; -} GstDeinterlaceMethodGreedyL; - -typedef struct -{ - GstDeinterlaceMethodClass parent_class; - void (*scanline) (GstDeinterlaceMethodGreedyL * self, uint8_t * L2, - uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size); -} GstDeinterlaceMethodGreedyLClass; - -// 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 inline void -deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self, - uint8_t * m0, uint8_t * t1, - uint8_t * b1, uint8_t * m2, uint8_t * output, int width) -{ - int avg, l2_diff, lp2_diff, max, min, best; - guint max_comb = self->max_comb; - - // L2 == m0 - // L1 == t1 - // L3 == b1 - // LP2 == m2 - - while (width--) { - avg = (*t1 + *b1) / 2; - - l2_diff = ABS (*m0 - avg); - lp2_diff = ABS (*m2 - avg); - - if (l2_diff > lp2_diff) - best = *m2; - else - best = *m0; - - max = MAX (*t1, *b1); - min = MIN (*t1, *b1); - - if (max < 256 - max_comb) - max += max_comb; - else - max = 255; - - if (min > max_comb) - min -= max_comb; - else - min = 0; - - *output = CLAMP (best, min, max); - - // Advance to the next set of pixels. - output += 1; - m0 += 1; - t1 += 1; - b1 += 1; - m2 += 1; - } -} - -#ifdef BUILD_X86_ASM -#include "mmx.h" -static void -deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self, - uint8_t * m0, uint8_t * t1, - uint8_t * b1, uint8_t * m2, uint8_t * output, int width) -{ - mmx_t MaxComb; - mmx_t ShiftMask; - - // How badly do we let it weave? 0-255 - MaxComb.ub[0] = self->max_comb; - MaxComb.ub[1] = self->max_comb; - MaxComb.ub[2] = self->max_comb; - MaxComb.ub[3] = self->max_comb; - MaxComb.ub[4] = self->max_comb; - MaxComb.ub[5] = self->max_comb; - MaxComb.ub[6] = self->max_comb; - MaxComb.ub[7] = self->max_comb; - - ShiftMask.ub[0] = 0x7f; - ShiftMask.ub[1] = 0x7f; - ShiftMask.ub[2] = 0x7f; - ShiftMask.ub[3] = 0x7f; - ShiftMask.ub[4] = 0x7f; - ShiftMask.ub[5] = 0x7f; - ShiftMask.ub[6] = 0x7f; - ShiftMask.ub[7] = 0x7f; - - // L2 == m0 - // L1 == t1 - // L3 == b1 - // LP2 == m2 - - movq_m2r (MaxComb, mm6); - - for (; width > 7; width -= 8) { - 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 - movq_r2r (mm3, mm5); // L3 - psrlw_i2r (1, mm4); // L1/2 - pand_m2r (ShiftMask, mm4); - psrlw_i2r (1, mm5); // L3/2 - pand_m2r (ShiftMask, mm5); - paddusb_r2r (mm5, 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) - - // 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_r2r (mm6, mm2); // increase max by diff - psubusb_r2r (mm6, 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 - - movq_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; - } - emms (); - if (width > 0) - deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output, - width); -} - -#include "sse.h" - -static void -deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL * - self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, - uint8_t * output, int width) -{ - mmx_t MaxComb; - - // How badly do we let it weave? 0-255 - MaxComb.ub[0] = self->max_comb; - MaxComb.ub[1] = self->max_comb; - MaxComb.ub[2] = self->max_comb; - MaxComb.ub[3] = self->max_comb; - MaxComb.ub[4] = self->max_comb; - MaxComb.ub[5] = self->max_comb; - MaxComb.ub[6] = self->max_comb; - MaxComb.ub[7] = self->max_comb; - - // L2 == m0 - // L1 == t1 - // L3 == b1 - // LP2 == m2 - - movq_m2r (MaxComb, mm6); - - for (; width > 7; width -= 8) { - 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) - - // 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 - pxor_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 - pmaxub_r2r (mm3, mm2); // now = Max(L1,L3) - - pminub_r2r (mm1, mm3); // now = Min(L1,L3) - - // allow the value to be above the high or below the low by amt of MaxComb - paddusb_r2r (mm6, mm2); // increase max by diff - psubusb_r2r (mm6, mm3); // lower min by diff - - - pmaxub_r2r (mm3, mm4); // now = Max(best,Min(L1,L3) - pminub_r2r (mm4, mm2); // now = Min( Max(best, Min(L1,L3)), L2 )=L2 clipped - - movq_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; - } - emms (); - - if (width > 0) - deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output, - width); -} - -#endif - -static void -deinterlace_frame_di_greedy (GstDeinterlaceMethod * d_method, - GstDeinterlace2 * object, GstBuffer * outbuf) -{ - GstDeinterlaceMethodGreedyL *self = - GST_DEINTERLACE_METHOD_GREEDY_L (d_method); - GstDeinterlaceMethodGreedyLClass *klass = - GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self); - int InfoIsOdd = 0; - int Line; - unsigned int Pitch = object->field_stride; - unsigned char *L1; // ptr to Line1, of 3 - unsigned char *L2; // ptr to Line2, the weave line - unsigned char *L3; // ptr to Line3 - - unsigned char *L2P; // ptr to prev Line2 - unsigned char *Dest = GST_BUFFER_DATA (outbuf); - - // copy first even line no matter what, and the first odd line if we're - // processing an EVEN field. (note diff from other deint rtns.) - - if (object->field_history[object->history_count - 1].flags == - PICTURE_INTERLACED_BOTTOM) { - InfoIsOdd = 1; - - L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); - L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf); - L3 = L1 + Pitch; - L2P = - GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf); - - // copy first even line - oil_memcpy (Dest, L1, object->row_stride); - Dest += object->row_stride; - } else { - InfoIsOdd = 0; - L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); - L2 = GST_BUFFER_DATA (object->field_history[object->history_count - - 1].buf) + Pitch; - L3 = L1 + Pitch; - L2P = - GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) + - Pitch; - - // copy first even line - oil_memcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf), - object->row_stride); - Dest += object->row_stride; - // then first odd line - oil_memcpy (Dest, L1, object->row_stride); - Dest += object->row_stride; - } - - for (Line = 0; Line < (object->field_height - 1); ++Line) { - klass->scanline (self, L2, L1, L3, L2P, Dest, object->row_stride); - Dest += object->row_stride; - oil_memcpy (Dest, L3, object->row_stride); - Dest += object->row_stride; - - L1 += Pitch; - L2 += Pitch; - L3 += Pitch; - L2P += Pitch; - } - - if (InfoIsOdd) { - oil_memcpy (Dest, L2, object->row_stride); - } -} - - -G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l, - GST_TYPE_DEINTERLACE_METHOD); - -enum -{ - ARG_0, - ARG_MAX_COMB -}; - -static void -gst_deinterlace_method_greedy_l_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object); - - switch (prop_id) { - case ARG_MAX_COMB: - self->max_comb = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gst_deinterlace_method_greedy_l_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object); - - switch (prop_id) { - case ARG_MAX_COMB: - g_value_set_uint (value, self->max_comb); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass * - klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GObjectClass *gobject_class = (GObjectClass *) klass; -#ifdef BUILD_X86_ASM - guint cpu_flags = oil_cpu_get_flags (); -#endif - - gobject_class->set_property = gst_deinterlace_method_greedy_l_set_property; - gobject_class->get_property = gst_deinterlace_method_greedy_l_get_property; - - g_object_class_install_property (gobject_class, ARG_MAX_COMB, - g_param_spec_uint ("max-comb", - "Max comb", - "Max Comb", 0, 255, 15, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - dim_class->fields_required = 4; - dim_class->deinterlace_frame = deinterlace_frame_di_greedy; - dim_class->name = "Motion Adaptive: Simple Detection"; - dim_class->nick = "greedyl"; - dim_class->latency = 1; - -#ifdef BUILD_X86_ASM - if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { - klass->scanline = deinterlace_greedy_packed422_scanline_mmxext; - } else if (cpu_flags & OIL_IMPL_FLAG_MMX) { - klass->scanline = deinterlace_greedy_packed422_scanline_mmx; - } else { - klass->scanline = deinterlace_greedy_packed422_scanline_c; - } -#else - klass->scanline = deinterlace_greedy_packed422_scanline_c; -#endif -} - -static void -gst_deinterlace_method_greedy_l_init (GstDeinterlaceMethodGreedyL * self) -{ - self->max_comb = 15; -} diff --git a/gst/deinterlace2/tvtime/greedyh.asm b/gst/deinterlace2/tvtime/greedyh.asm deleted file mode 100644 index 86e97c58..00000000 --- a/gst/deinterlace2/tvtime/greedyh.asm +++ /dev/null @@ -1,250 +0,0 @@ -/* - * - * GStreamer - * Copyright (c) 2001 Tom Barry. All rights reserved. - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -/* - * Relicensed for GStreamer from GPL to LGPL with permit from Tom Barry. - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - - -#include "x86-64_macros.inc" - -void -FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P, - uint8_t * Dest, int size) -{ - - // in tight loop some vars are accessed faster in local storage - int64_t YMask = 0x00ff00ff00ff00ffull; // to keep only luma - int64_t UVMask = 0xff00ff00ff00ff00ull; // to keep only chroma - int64_t ShiftMask = 0xfefefefefefefefeull; // to avoid shifting chroma to luma - int64_t QW256 = 0x0100010001000100ull; // 4 256's - int64_t MaxComb; - int64_t MotionThreshold; - int64_t MotionSense; - int64_t i; - long LoopCtr; - long oldbx; - - int64_t QW256B; - int64_t LastAvg = 0; //interp value from left qword - - // FIXME: Use C implementation if the width is not a multiple of 4 - // Do something more optimal later - if (size % 8 != 0) - greedyDScaler_C (self, L1, L2, L3, L2P, Dest, size); - - // Set up our two parms that are actually evaluated for each pixel - i = self->max_comb; - MaxComb = - i << 56 | i << 48 | i << 40 | i << 32 | i << 24 | i << 16 | i << 8 | i; - - i = self->motion_threshold; // scale to range of 0-257 - MotionThreshold = i << 48 | i << 32 | i << 16 | i | UVMask; - - i = self->motion_sense; // scale to range of 0-257 - MotionSense = i << 48 | i << 32 | i << 16 | i; - - i = 0xffffffff - 256; - QW256B = i << 48 | i << 32 | i << 16 | i; // save a couple instr on PMINSW instruct. - - LoopCtr = size / 8 - 1; // there are LineLength / 8 qwords per line but do 1 less, adj at end of loop - - // For ease of reading, the comments below assume that we're operating on an odd - // field (i.e., that InfoIsOdd is true). Assume the obvious for even lines.. - __asm__ __volatile__ ( - // save ebx (-fPIC) - MOVX " %%" XBX ", %[oldbx]\n\t" - MOVX " %[L1], %%" XAX "\n\t" - LEAX " 8(%%" XAX "), %%" XBX "\n\t" // next qword needed by DJR - MOVX " %[L3], %%" XCX "\n\t" - SUBX " %%" XAX ", %%" XCX "\n\t" // carry L3 addr as an offset - MOVX " %[L2P], %%" XDX "\n\t" - MOVX " %[L2], %%" XSI "\n\t" - MOVX " %[Dest], %%" XDI "\n\t" // DL1 if Odd or DL2 if Even - - ".align 8\n\t" - "1:\n\t" - "movq (%%" XSI "), %%mm0\n\t" // L2 - the newest weave pixel value - "movq (%%" XAX "), %%mm1\n\t" // L1 - the top pixel - "movq (%%" XDX "), %%mm2\n\t" // L2P - the prev weave pixel - "movq (%%" XAX ", %%" XCX "), %%mm3\n\t" // L3, next odd row - "movq %%mm1, %%mm6\n\t" // L1 - get simple single pixel interp - - // pavgb mm6, mm3 // use macro below - V_PAVGB ("%%mm6", "%%mm3", "%%mm4", "%[ShiftMask]") - - // DJR - Diagonal Jaggie Reduction - // In the event that we are going to use an average (Bob) pixel we do not want a jagged - // stair step effect. To combat this we avg in the 2 horizontally adjacen pixels into the - // interpolated Bob mix. This will do horizontal smoothing for only the Bob'd pixels. - - "movq %[LastAvg], %%mm4\n\t" // the bob value from prev qword in row - "movq %%mm6, %[LastAvg]\n\t" // save for next pass - "psrlq $48, %%mm4\n\t" // right justify 1 pixel - "movq %%mm6, %%mm7\n\t" // copy of simple bob pixel - "psllq $16, %%mm7\n\t" // left justify 3 pixels - "por %%mm7, %%mm4\n\t" // and combine - "movq (%%" XBX "), %%mm5\n\t" // next horiz qword from L1 - // pavgb mm5, qword ptr[ebx+ecx] // next horiz qword from L3, use macro below - - V_PAVGB ("%%mm5", "(%%" XBX ",%%" XCX ")", "%%mm7", "%[ShiftMask]") - "psllq $48, %%mm5\n\t" // left just 1 pixel - "movq %%mm6, %%mm7\n\t" // another copy of simple bob pixel - "psrlq $16, %%mm7\n\t" // right just 3 pixels - "por %%mm7, %%mm5\n\t" // combine - // pavgb mm4, mm5 // avg of forward and prev by 1 pixel, use macro - V_PAVGB ("%%mm4", "%%mm5", "%%mm5", "%[ShiftMask]") // mm5 gets modified if MMX - // pavgb mm6, mm4 // avg of center and surround interp vals, use macro - V_PAVGB ("%%mm6", "%%mm4", "%%mm7", "%[ShiftMask]") - - // Don't do any more averaging than needed for mmx. It hurts performance and causes rounding errors. -#ifndef IS_MMX - // pavgb mm4, mm6 // 1/4 center, 3/4 adjacent - V_PAVGB ("%%mm4", "%%mm6", "%%mm7", "%[ShiftMask]") - // pavgb mm6, mm4 // 3/8 center, 5/8 adjacent - V_PAVGB ("%%mm6", "%%mm4", "%%mm7", "%[ShiftMask]") -#endif - - // get abs value of possible L2 comb - "movq %%mm6, %%mm4\n\t" // work copy of interp val - "movq %%mm2, %%mm7\n\t" // L2 - "psubusb %%mm4, %%mm7\n\t" // L2 - avg - "movq %%mm4, %%mm5\n\t" // avg - "psubusb %%mm2, %%mm5\n\t" // avg - L2 - "por %%mm7, %%mm5\n\t" // abs(avg-L2) - - // get abs value of possible L2P comb - "movq %%mm0, %%mm7\n\t" // L2P - "psubusb %%mm4, %%mm7\n\t" // L2P - avg - "psubusb %%mm0, %%mm4\n\t" // avg - L2P - "por %%mm7, %%mm4\n\t" // abs(avg-L2P) - - // use L2 or L2P depending upon which makes smaller comb - "psubusb %%mm5, %%mm4\n\t" // see if it goes to zero - "psubusb %%mm5, %%mm5\n\t" // 0 - "pcmpeqb %%mm5, %%mm4\n\t" // if (mm4=0) then FF else 0 - "pcmpeqb %%mm4, %%mm5\n\t" // opposite of mm4 - - // if Comb(L2P) <= Comb(L2) then mm4=ff, mm5=0 else mm4=0, mm5 = 55 - "pand %%mm2, %%mm5\n\t" // use L2 if mm5 == ff, else 0 - "pand %%mm0, %%mm4\n\t" // use L2P if mm4 = ff, else 0 - "por %%mm5, %%mm4\n\t" // may the best win - - // Inventory: at this point we have the following values: - // mm0 = L2P (or L2) - // mm1 = L1 - // mm2 = L2 (or L2P) - // mm3 = L3 - // mm4 = the best of L2,L2P weave pixel, base upon comb - // mm6 = the avg interpolated value, if we need to use it - // Let's measure movement, as how much the weave pixel has changed - - "movq %%mm2, %%mm7\n\t" - "psubusb %%mm0, %%mm2\n\t" - "psubusb %%mm7, %%mm0\n\t" - "por %%mm2, %%mm0\n\t" // abs value of change, used later - - // Now lets clip our chosen value to be not outside of the range - // of the high/low range L1-L3 by more than MaxComb. - // This allows some comb but limits the damages and also allows more - // detail than a boring oversmoothed clip. - - "movq %%mm1, %%mm2\n\t" // copy L1 - // pmaxub mm2, mm3 // use macro - V_PMAXUB ("%%mm2", "%%mm3") // now = Max(L1,L3) - "movq %%mm1, %%mm5\n\t" // copy L1 - // pminub mm5, mm3 // now = Min(L1,L3), use macro - V_PMINUB ("%%mm5", "%%mm3", "%%mm7") - - // allow the value to be above the high or below the low by amt of MaxComb - "psubusb %[MaxComb], %%mm5\n\t" // lower min by diff - "paddusb %[MaxComb], %%mm2\n\t" // increase max by diff - // pmaxub mm4, mm5 // now = Max(best,Min(L1,L3) use macro - V_PMAXUB ("%%mm4", "%%mm5") - // pminub mm4, mm2 // now = Min( Max(best, Min(L1,L3), L2 )=L2 clipped - V_PMINUB ("%%mm4", "%%mm2", "%%mm7") - - // Blend weave pixel with bob pixel, depending on motion val in mm0 - "psubusb %[MotionThreshold], %%mm0\n\t" // test Threshold, clear chroma change >>>?? - "pmullw %[MotionSense], %%mm0\n\t" // mul by user factor, keep low 16 bits - "movq %[QW256], %%mm7\n\t" -#ifdef IS_MMXEXT - "pminsw %%mm7, %%mm0\n\t" // max = 256 -#else - "paddusw %[QW256B], %%mm0\n\t" // add, may sat at fff.. - "psubusw %[QW256B], %%mm0\n\t" // now = Min(L1,256) -#endif - "psubusw %%mm0, %%mm7\n\t" // so the 2 sum to 256, weighted avg - "movq %%mm4, %%mm2\n\t" // save weave chroma info before trashing - "pand %[YMask], %%mm4\n\t" // keep only luma from calc'd value - "pmullw %%mm7, %%mm4\n\t" // use more weave for less motion - "pand %[YMask], %%mm6\n\t" // keep only luma from calc'd value - "pmullw %%mm0, %%mm6\n\t" // use more bob for large motion - "paddusw %%mm6, %%mm4\n\t" // combine - "psrlw $8, %%mm4\n\t" // div by 256 to get weighted avg - // chroma comes from weave pixel - "pand %[UVMask], %%mm2\n\t" // keep chroma - "por %%mm4, %%mm2\n\t" // and combine - V_MOVNTQ ("(%%" XDI ")", "%%mm2") // move in our clipped best, use macro - // bump ptrs and loop - LEAX " 8(%%" XAX "), %%" XAX "\n\t" - LEAX " 8(%%" XBX "), %%" XBX "\n\t" - LEAX " 8(%%" XDX "), %%" XDX "\n\t" - LEAX " 8(%%" XDI "), %%" XDI "\n\t" - LEAX " 8(%%" XSI "), %%" XSI "\n\t" - DECX " %[LoopCtr]\n\t" - - "jg 1b\n\t" // loop if not to last line - // note P-III default assumes backward branches taken - "jl 1f\n\t" // done - MOVX " %%" XAX ", %%" XBX "\n\t" // sharpness lookahead 1 byte only, be wrong on 1 - "jmp 1b\n\t" - - "1:\n\t" - MOVX " %[oldbx], %%" XBX "\n\t" - "emms\n\t": /* no outputs */ - - :[LastAvg] "m" (LastAvg), - [L1] "m" (L1), - [L3] "m" (L3), - [L2P] "m" (L2P), - [L2] "m" (L2), - [Dest] "m" (Dest), - [ShiftMask] "m" (ShiftMask), - [MaxComb] "m" (MaxComb), - [MotionThreshold] "m" (MotionThreshold), - [MotionSense] "m" (MotionSense), - [QW256B] "m" (QW256B), - [YMask] "m" (YMask), - [UVMask] "m" (UVMask), - [LoopCtr] "m" (LoopCtr), - [QW256] "m" (QW256), - [oldbx] "m" (oldbx) - : XAX, XCX, XDX, XSI, XDI, - "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", -#ifdef __MMX__ - "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", -#endif - "memory", "cc"); -} diff --git a/gst/deinterlace2/tvtime/greedyh.c b/gst/deinterlace2/tvtime/greedyh.c deleted file mode 100644 index a5aafd18..00000000 --- a/gst/deinterlace2/tvtime/greedyh.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * - * GStreamer - * Copyright (C) 2004 Billy Biggs - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs. - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "greedyhmacros.h" - -#include -#include "_stdint.h" -#include - -#include "gst/gst.h" -#include "plugins.h" -#include "gstdeinterlace2.h" - -#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H)) -#define GST_IS_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H)) -#define GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass)) -#define GST_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyH)) -#define GST_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass)) -#define GST_DEINTERLACE_METHOD_GREEDY_H_CAST(obj) ((GstDeinterlaceMethodGreedyH*)(obj)) - -GType gst_deinterlace_method_greedy_h_get_type (void); - -typedef struct -{ - GstDeinterlaceMethod parent; - - guint max_comb, motion_threshold, motion_sense; -} GstDeinterlaceMethodGreedyH; - -typedef struct -{ - GstDeinterlaceMethodClass parent_class; - void (*scanline) (GstDeinterlaceMethodGreedyH * self, uint8_t * L2, - uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size); -} GstDeinterlaceMethodGreedyHClass; - -void -greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2, - uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size) -{ - int Pos; - uint8_t l1_l, l1_1_l, l3_l, l3_1_l; - uint8_t l1_c, l1_1_c, l3_c, l3_1_c; - uint8_t avg_l, avg_c, avg_l_1, avg_c_1; - uint8_t avg_l__1 = 0, avg_c__1 = 0; - uint8_t avg_s_l, avg_s_c; - uint8_t avg_sc_l, avg_sc_c; - uint8_t best_l, best_c; - uint16_t mov_l; - uint8_t out_l, out_c; - uint8_t l2_l, l2_c, lp2_l, lp2_c; - uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff; - uint8_t min_l, min_c, max_l, max_c; - guint max_comb = self->max_comb; - guint motion_sense = self->motion_sense; - guint motion_threshold = self->motion_threshold; - - for (Pos = 0; Pos < size; Pos += 2) { - l1_l = L1[0]; - l1_c = L1[1]; - l3_l = L3[0]; - l3_c = L3[1]; - - if (Pos == size - 1) { - l1_1_l = l1_l; - l1_1_c = l1_c; - l3_1_l = l3_l; - l3_1_c = l3_c; - } else { - l1_1_l = L1[2]; - l1_1_c = L1[3]; - l3_1_l = L3[2]; - l3_1_c = L3[3]; - } - - /* Average of L1 and L3 */ - avg_l = (l1_l + l3_l) / 2; - avg_c = (l1_c + l3_c) / 2; - - if (Pos == 0) { - avg_l__1 = avg_l; - avg_c__1 = avg_c; - } - - /* Average of next L1 and next L3 */ - avg_l_1 = (l1_1_l + l3_1_l) / 2; - avg_c_1 = (l1_1_c + l3_1_c) / 2; - - /* Calculate average of one pixel forward and previous */ - avg_s_l = (avg_l__1 + avg_l_1) / 2; - avg_s_c = (avg_c__1 + avg_c_1) / 2; - - /* Calculate average of center and surrounding pixels */ - avg_sc_l = (avg_l + avg_s_l) / 2; - avg_sc_c = (avg_c + avg_s_c) / 2; - - /* move forward */ - avg_l__1 = avg_l; - avg_c__1 = avg_c; - - /* Get best L2/L2P, i.e. least diff from above average */ - l2_l = L2[0]; - l2_c = L2[1]; - lp2_l = L2P[0]; - lp2_c = L2P[1]; - - l2_l_diff = ABS (l2_l - avg_sc_l); - l2_c_diff = ABS (l2_c - avg_sc_c); - - lp2_l_diff = ABS (lp2_l - avg_sc_l); - lp2_c_diff = ABS (lp2_c - avg_sc_c); - - if (l2_l_diff > lp2_l_diff) - best_l = lp2_l; - else - best_l = l2_l; - - if (l2_c_diff > lp2_c_diff) - best_c = lp2_c; - else - best_c = l2_c; - - /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */ - max_l = MAX (l1_l, l3_l); - min_l = MIN (l1_l, l3_l); - - if (max_l < 256 - max_comb) - max_l += max_comb; - else - max_l = 255; - - if (min_l > max_comb) - min_l -= max_comb; - else - min_l = 0; - - max_c = MAX (l1_c, l3_c); - min_c = MIN (l1_c, l3_c); - - if (max_c < 256 - max_comb) - max_c += max_comb; - else - max_c = 255; - - if (min_c > max_comb) - min_c -= max_comb; - else - min_c = 0; - - out_l = CLAMP (best_l, min_l, max_l); - out_c = CLAMP (best_c, min_c, max_c); - - /* Do motion compensation for luma, i.e. how much - * the weave pixel differs */ - mov_l = ABS (l2_l - lp2_l); - if (mov_l > motion_threshold) - mov_l -= motion_threshold; - else - mov_l = 0; - - mov_l = mov_l * motion_sense; - if (mov_l > 256) - mov_l = 256; - - /* Weighted sum on clipped weave pixel and average */ - out_l = (out_l * (256 - mov_l) + avg_sc_l * mov_l) / 256; - - Dest[0] = out_l; - Dest[1] = out_c; - - Dest += 2; - L1 += 2; - L2 += 2; - L3 += 2; - L2P += 2; - } -} - -#ifdef BUILD_X86_ASM - -#define IS_MMXEXT -#define SIMD_TYPE MMXEXT -#define FUNCT_NAME greedyDScaler_MMXEXT -#include "greedyh.asm" -#undef SIMD_TYPE -#undef IS_MMXEXT -#undef FUNCT_NAME - -#define IS_3DNOW -#define SIMD_TYPE 3DNOW -#define FUNCT_NAME greedyDScaler_3DNOW -#include "greedyh.asm" -#undef SIMD_TYPE -#undef IS_3DNOW -#undef FUNCT_NAME - -#define IS_MMX -#define SIMD_TYPE MMX -#define FUNCT_NAME greedyDScaler_MMX -#include "greedyh.asm" -#undef SIMD_TYPE -#undef IS_MMX -#undef FUNCT_NAME - -#endif - -static void -deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method, - GstDeinterlace2 * object, GstBuffer * outbuf) -{ - GstDeinterlaceMethodGreedyH *self = - GST_DEINTERLACE_METHOD_GREEDY_H (d_method); - GstDeinterlaceMethodGreedyHClass *klass = - GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self); - int InfoIsOdd = 0; - int Line; - unsigned int Pitch = object->field_stride; - - unsigned char *L1; // ptr to Line1, of 3 - unsigned char *L2; // ptr to Line2, the weave line - unsigned char *L3; // ptr to Line3 - - unsigned char *L2P; // ptr to prev Line2 - unsigned char *Dest = GST_BUFFER_DATA (outbuf); - - // copy first even line no matter what, and the first odd line if we're - // processing an EVEN field. (note diff from other deint rtns.) - - if (object->field_history[object->history_count - 1].flags == - PICTURE_INTERLACED_BOTTOM) { - InfoIsOdd = 1; - - L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); - L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf); - L3 = L1 + Pitch; - L2P = - GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf); - - // copy first even line - oil_memcpy (Dest, L1, object->row_stride); - Dest += object->row_stride; - } else { - InfoIsOdd = 0; - L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); - L2 = GST_BUFFER_DATA (object->field_history[object->history_count - - 1].buf) + Pitch; - L3 = L1 + Pitch; - L2P = - GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) + - Pitch; - - // copy first even line - oil_memcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf), - object->row_stride); - Dest += object->row_stride; - // then first odd line - oil_memcpy (Dest, L1, object->row_stride); - Dest += object->row_stride; - } - - for (Line = 0; Line < (object->field_height - 1); ++Line) { - klass->scanline (self, L1, L2, L3, L2P, Dest, object->row_stride); - Dest += object->row_stride; - oil_memcpy (Dest, L3, object->row_stride); - Dest += object->row_stride; - - L1 += Pitch; - L2 += Pitch; - L3 += Pitch; - L2P += Pitch; - } - - if (InfoIsOdd) { - oil_memcpy (Dest, L2, object->row_stride); - } -} - -G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h, - GST_TYPE_DEINTERLACE_METHOD); - -enum -{ - ARG_0, - ARG_MAX_COMB, - ARG_MOTION_THRESHOLD, - ARG_MOTION_SENSE -}; - -static void -gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object); - - switch (prop_id) { - case ARG_MAX_COMB: - self->max_comb = g_value_get_uint (value); - break; - case ARG_MOTION_THRESHOLD: - self->motion_threshold = g_value_get_uint (value); - break; - case ARG_MOTION_SENSE: - self->motion_sense = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object); - - switch (prop_id) { - case ARG_MAX_COMB: - g_value_set_uint (value, self->max_comb); - break; - case ARG_MOTION_THRESHOLD: - g_value_set_uint (value, self->motion_threshold); - break; - case ARG_MOTION_SENSE: - g_value_set_uint (value, self->motion_sense); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass * - klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GObjectClass *gobject_class = (GObjectClass *) klass; -#ifdef BUILD_X86_ASM - guint cpu_flags = oil_cpu_get_flags (); -#endif - - gobject_class->set_property = gst_deinterlace_method_greedy_h_set_property; - gobject_class->get_property = gst_deinterlace_method_greedy_h_get_property; - - g_object_class_install_property (gobject_class, ARG_MAX_COMB, - g_param_spec_uint ("max-comb", - "Max comb", - "Max Comb", 0, 255, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - g_object_class_install_property (gobject_class, ARG_MOTION_THRESHOLD, - g_param_spec_uint ("motion-threshold", - "Motion Threshold", - "Motion Threshold", - 0, 255, 25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - g_object_class_install_property (gobject_class, ARG_MOTION_SENSE, - g_param_spec_uint ("motion-sense", - "Motion Sense", - "Motion Sense", - 0, 255, 30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - dim_class->fields_required = 4; - dim_class->deinterlace_frame = deinterlace_frame_di_greedyh; - dim_class->name = "Motion Adaptive: Advanced Detection"; - dim_class->nick = "greedyh"; - dim_class->latency = 1; - -#ifdef BUILD_X86_ASM - if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { - klass->scanline = greedyDScaler_MMXEXT; - } else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) { - klass->scanline = greedyDScaler_3DNOW; - } else if (cpu_flags & OIL_IMPL_FLAG_MMX) { - klass->scanline = greedyDScaler_MMX; - } else { - klass->scanline = greedyDScaler_C; - } -#else - klass->scanline = greedyDScaler_C; -#endif -} - -static void -gst_deinterlace_method_greedy_h_init (GstDeinterlaceMethodGreedyH * self) -{ - self->max_comb = 5; - self->motion_threshold = 25; - self->motion_sense = 30; -} diff --git a/gst/deinterlace2/tvtime/greedyhmacros.h b/gst/deinterlace2/tvtime/greedyhmacros.h deleted file mode 100644 index 0386c28e..00000000 --- a/gst/deinterlace2/tvtime/greedyhmacros.h +++ /dev/null @@ -1,75 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2001 Tom Barry. All rights reserved. -///////////////////////////////////////////////////////////////////////////// -// -// This file is subject to the terms of the GNU General Public License as -// published by the Free Software Foundation. A copy of this license is -// included with this software distribution in the file COPYING. If you -// do not have a copy, you may obtain a copy by writing to the Free -// Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -// -// This software 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 -// -///////////////////////////////////////////////////////////////////////////// - -// Define a few macros for CPU dependent instructions. -// I suspect I don't really understand how the C macro preprocessor works but -// this seems to get the job done. // TRB 7/01 - -// BEFORE USING THESE YOU MUST SET: - -// #define SIMD_TYPE MMXEXT (or MMX or 3DNOW) - -// some macros for pavgb instruction -// V_PAVGB(mmr1, mmr2, mmr work register, smask) mmr2 may = mmrw if you can trash it - -#define V_PAVGB_MMX(mmr1, mmr2, mmrw, smask) \ - "movq "mmr2", "mmrw"\n\t" \ - "pand "smask", "mmrw"\n\t" \ - "psrlw $1, "mmrw"\n\t" \ - "pand "smask", "mmr1"\n\t" \ - "psrlw $1, "mmr1"\n\t" \ - "paddusb "mmrw", "mmr1"\n\t" -#define V_PAVGB_MMXEXT(mmr1, mmr2, mmrw, smask) "pavgb "mmr2", "mmr1"\n\t" -#define V_PAVGB_3DNOW(mmr1, mmr2, mmrw, smask) "pavgusb "mmr2", "mmr1"\n\t" -#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SIMD_TYPE) -#define V_PAVGB2(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) -#define V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB_##simd_type(mmr1, mmr2, mmrw, smask) - -// some macros for pmaxub instruction -#define V_PMAXUB_MMX(mmr1, mmr2) \ - "psubusb "mmr2", "mmr1"\n\t" \ - "paddusb "mmr2", "mmr1"\n\t" -#define V_PMAXUB_MMXEXT(mmr1, mmr2) "pmaxub "mmr2", "mmr1"\n\t" -#define V_PMAXUB_3DNOW(mmr1, mmr2) V_PMAXUB_MMX(mmr1, mmr2) // use MMX version -#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SIMD_TYPE) -#define V_PMAXUB2(mmr1, mmr2, simd_type) V_PMAXUB3(mmr1, mmr2, simd_type) -#define V_PMAXUB3(mmr1, mmr2, simd_type) V_PMAXUB_##simd_type(mmr1, mmr2) - -// some macros for pminub instruction -// V_PMINUB(mmr1, mmr2, mmr work register) mmr2 may NOT = mmrw -#define V_PMINUB_MMX(mmr1, mmr2, mmrw) \ - "pcmpeqb "mmrw", "mmrw"\n\t" \ - "psubusb "mmr2", "mmrw"\n\t" \ - "paddusb "mmrw", "mmr1"\n\t" \ - "psubusb "mmrw", "mmr1"\n\t" -#define V_PMINUB_MMXEXT(mmr1, mmr2, mmrw) "pminub "mmr2", "mmr1"\n\t" -#define V_PMINUB_3DNOW(mmr1, mmr2, mmrw) V_PMINUB_MMX(mmr1, mmr2, mmrw) // use MMX version -#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SIMD_TYPE) -#define V_PMINUB2(mmr1, mmr2, mmrw, simd_type) V_PMINUB3(mmr1, mmr2, mmrw, simd_type) -#define V_PMINUB3(mmr1, mmr2, mmrw, simd_type) V_PMINUB_##simd_type(mmr1, mmr2, mmrw) - -// some macros for movntq instruction -// V_MOVNTQ(mmr1, mmr2) -#define V_MOVNTQ_MMX(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ_3DNOW(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ_MMXEXT(mmr1, mmr2) "movntq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SIMD_TYPE) -#define V_MOVNTQ2(mmr1, mmr2, simd_type) V_MOVNTQ3(mmr1, mmr2, simd_type) -#define V_MOVNTQ3(mmr1, mmr2, simd_type) V_MOVNTQ_##simd_type(mmr1, mmr2) - -// end of macros - diff --git a/gst/deinterlace2/tvtime/linear.c b/gst/deinterlace2/tvtime/linear.c deleted file mode 100644 index 42403e49..00000000 --- a/gst/deinterlace2/tvtime/linear.c +++ /dev/null @@ -1,214 +0,0 @@ -/** - * Copyright (C) 2002 Billy Biggs . - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_LINEAR (gst_deinterlace_method_linear_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_LINEAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR)) -#define GST_IS_DEINTERLACE_METHOD_LINEAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR)) -#define GST_DEINTERLACE_METHOD_LINEAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR, GstDeinterlaceMethodLinearClass)) -#define GST_DEINTERLACE_METHOD_LINEAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR, GstDeinterlaceMethodLinear)) -#define GST_DEINTERLACE_METHOD_LINEAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR, GstDeinterlaceMethodLinearClass)) -#define GST_DEINTERLACE_METHOD_LINEAR_CAST(obj) ((GstDeinterlaceMethodLinear*)(obj)) - -GType gst_deinterlace_method_linear_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodLinear; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodLinearClass; - -static void -deinterlace_scanline_linear_c (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - gint i; - - width *= 2; - for (i = 0; i < width; i++) - out[i] = (scanlines->t0[i] + scanlines->b0[i]) / 2; -} - -#ifdef BUILD_X86_ASM -#include "mmx.h" -static void -deinterlace_scanline_linear_mmx (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - const mmx_t shiftmask = { 0xfefffefffefffeffULL }; /* To avoid shifting chroma to luma. */ - int i; - guint8 *bot = scanlines->b0, *top = scanlines->t0; - - for (i = width / 16; i; --i) { - movq_m2r (*bot, mm0); - movq_m2r (*top, mm1); - movq_m2r (*(bot + 8), mm2); - movq_m2r (*(top + 8), mm3); - movq_m2r (*(bot + 16), mm4); - movq_m2r (*(top + 16), mm5); - movq_m2r (*(bot + 24), mm6); - movq_m2r (*(top + 24), mm7); - pand_m2r (shiftmask, mm0); - pand_m2r (shiftmask, mm1); - pand_m2r (shiftmask, mm2); - pand_m2r (shiftmask, mm3); - pand_m2r (shiftmask, mm4); - pand_m2r (shiftmask, mm5); - pand_m2r (shiftmask, mm6); - pand_m2r (shiftmask, mm7); - psrlw_i2r (1, mm0); - psrlw_i2r (1, mm1); - psrlw_i2r (1, mm2); - psrlw_i2r (1, mm3); - psrlw_i2r (1, mm4); - psrlw_i2r (1, mm5); - psrlw_i2r (1, mm6); - psrlw_i2r (1, mm7); - paddb_r2r (mm1, mm0); - paddb_r2r (mm3, mm2); - paddb_r2r (mm5, mm4); - paddb_r2r (mm7, mm6); - movq_r2m (mm0, *out); - movq_r2m (mm2, *(out + 8)); - movq_r2m (mm4, *(out + 16)); - movq_r2m (mm6, *(out + 24)); - out += 32; - top += 32; - bot += 32; - } - width = (width & 0xf); - - for (i = width / 4; i; --i) { - movq_m2r (*bot, mm0); - movq_m2r (*top, mm1); - pand_m2r (shiftmask, mm0); - pand_m2r (shiftmask, mm1); - psrlw_i2r (1, mm0); - psrlw_i2r (1, mm1); - paddb_r2r (mm1, mm0); - movq_r2m (mm0, *out); - out += 8; - top += 8; - bot += 8; - } - width = width & 0x7; - - /* Handle last few pixels. */ - for (i = width * 2; i; --i) { - *out++ = ((*top++) + (*bot++)) >> 1; - } - - emms (); -} - -#include "sse.h" -static void -deinterlace_scanline_linear_mmxext (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - gint i; - guint8 *bot = scanlines->b0, *top = scanlines->t0; - - for (i = width / 16; i; --i) { - movq_m2r (*bot, mm0); - movq_m2r (*top, mm1); - movq_m2r (*(bot + 8), mm2); - movq_m2r (*(top + 8), mm3); - movq_m2r (*(bot + 16), mm4); - movq_m2r (*(top + 16), mm5); - movq_m2r (*(bot + 24), mm6); - movq_m2r (*(top + 24), mm7); - pavgb_r2r (mm1, mm0); - pavgb_r2r (mm3, mm2); - pavgb_r2r (mm5, mm4); - pavgb_r2r (mm7, mm6); - movntq_r2m (mm0, *out); - movntq_r2m (mm2, *(out + 8)); - movntq_r2m (mm4, *(out + 16)); - movntq_r2m (mm6, *(out + 24)); - out += 32; - top += 32; - bot += 32; - } - width = (width & 0xf); - - for (i = width / 4; i; --i) { - movq_m2r (*bot, mm0); - movq_m2r (*top, mm1); - pavgb_r2r (mm1, mm0); - movntq_r2m (mm0, *out); - out += 8; - top += 8; - bot += 8; - } - width = width & 0x7; - - /* Handle last few pixels. */ - for (i = width * 2; i; --i) { - *out++ = ((*top++) + (*bot++)) >> 1; - } - - emms (); -} - -#endif - -G_DEFINE_TYPE (GstDeinterlaceMethodLinear, gst_deinterlace_method_linear, - GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void -gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass * - klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; -#ifdef BUILD_X86_ASM - guint cpu_flags = oil_cpu_get_flags (); -#endif - - dim_class->fields_required = 1; - dim_class->name = "Television: Full resolution"; - dim_class->nick = "linear"; - dim_class->latency = 0; - - dism_class->interpolate_scanline = deinterlace_scanline_linear_c; - -#ifdef BUILD_X86_ASM - if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { - dism_class->interpolate_scanline = deinterlace_scanline_linear_mmxext; - } else if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { - dism_class->interpolate_scanline = deinterlace_scanline_linear_mmx; - } -#endif -} - -static void -gst_deinterlace_method_linear_init (GstDeinterlaceMethodLinear * self) -{ -} diff --git a/gst/deinterlace2/tvtime/linearblend.c b/gst/deinterlace2/tvtime/linearblend.c deleted file mode 100644 index c25c4d0e..00000000 --- a/gst/deinterlace2/tvtime/linearblend.c +++ /dev/null @@ -1,231 +0,0 @@ -/** - * Linear blend deinterlacing plugin. The idea for this algorithm came - * from the linear blend deinterlacer which originated in the mplayer - * sources. - * - * Copyright (C) 2002 Billy Biggs . - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND (gst_deinterlace_method_linear_blend_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_LINEAR_BLEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND)) -#define GST_IS_DEINTERLACE_METHOD_LINEAR_BLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND)) -#define GST_DEINTERLACE_METHOD_LINEAR_BLEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND, GstDeinterlaceMethodLinearBlendClass)) -#define GST_DEINTERLACE_METHOD_LINEAR_BLEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND, GstDeinterlaceMethodLinearBlend)) -#define GST_DEINTERLACE_METHOD_LINEAR_BLEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_LINEAR_BLEND, GstDeinterlaceMethodLinearBlendClass)) -#define GST_DEINTERLACE_METHOD_LINEAR_BLEND_CAST(obj) ((GstDeinterlaceMethodLinearBlend*)(obj)) - -GType gst_deinterlace_method_linear_blend_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodLinearBlend; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodLinearBlendClass; - - -static inline void -deinterlace_scanline_linear_blend_c (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - guint8 *t0 = scanlines->t0; - guint8 *b0 = scanlines->b0; - guint8 *m1 = scanlines->m1; - - width *= 2; - - while (width--) { - *out++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2; - } -} - -static inline void -deinterlace_scanline_linear_blend2_c (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - guint8 *m0 = scanlines->m0; - guint8 *t1 = scanlines->t1; - guint8 *b1 = scanlines->b1; - - width *= 2; - while (width--) { - *out++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2; - } -} - -#ifdef BUILD_X86_ASM -#include "mmx.h" -static inline void -deinterlace_scanline_linear_blend_mmx (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - guint8 *t0 = scanlines->t0; - guint8 *b0 = scanlines->b0; - guint8 *m1 = scanlines->m1; - gint 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, *out); - movd_r2m (mm5, *(out + 4)); - out += 8; - t0 += 8; - b0 += 8; - m1 += 8; - } - while (width--) { - *out++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2; - } - emms (); -} - -static inline void -deinterlace_scanline_linear_blend2_mmx (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - guint8 *m0 = scanlines->m0; - guint8 *t1 = scanlines->t1; - guint8 *b1 = scanlines->b1; - gint 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, *out); - movd_r2m (mm5, *(out + 4)); - out += 8; - t1 += 8; - b1 += 8; - m0 += 8; - } - while (width--) { - *out++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2; - } - emms (); -} - -#endif - -G_DEFINE_TYPE (GstDeinterlaceMethodLinearBlend, - gst_deinterlace_method_linear_blend, GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void - gst_deinterlace_method_linear_blend_class_init - (GstDeinterlaceMethodLinearBlendClass * klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; -#ifdef BUILD_X86_ASM - guint cpu_flags = oil_cpu_get_flags (); -#endif - - dim_class->fields_required = 2; - dim_class->name = "Blur: Temporal"; - dim_class->nick = "linearblend"; - dim_class->latency = 0; - - dism_class->interpolate_scanline = deinterlace_scanline_linear_blend_c; - dism_class->copy_scanline = deinterlace_scanline_linear_blend2_c; - -#ifdef BUILD_X86_ASM - if (cpu_flags & OIL_IMPL_FLAG_MMX) { - dism_class->interpolate_scanline = deinterlace_scanline_linear_blend_mmx; - dism_class->copy_scanline = deinterlace_scanline_linear_blend2_mmx; - } -#endif -} - -static void -gst_deinterlace_method_linear_blend_init (GstDeinterlaceMethodLinearBlend * - self) -{ -} diff --git a/gst/deinterlace2/tvtime/mmx.h b/gst/deinterlace2/tvtime/mmx.h deleted file mode 100644 index 3627e61b..00000000 --- a/gst/deinterlace2/tvtime/mmx.h +++ /dev/null @@ -1,723 +0,0 @@ -/* mmx.h - - MultiMedia eXtensions GCC interface library for IA32. - - To use this library, simply include this header file - and compile with GCC. You MUST have inlining enabled - in order for mmx_ok() to work; this can be done by - simply using -O on the GCC command line. - - Compiling with -DMMX_TRACE will cause detailed trace - output to be sent to stderr for each mmx operation. - This adds lots of code, and obviously slows execution to - a crawl, but can be very useful for debugging. - - THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT - LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR ANY PARTICULAR PURPOSE. - - 1997-98 by H. Dietz and R. Fisher - - History: - 97-98* R.Fisher Early versions - 980501 R.Fisher Original Release - 980611* H.Dietz Rewrite, correctly implementing inlines, and - R.Fisher including direct register accesses. - 980616 R.Fisher Release of 980611 as 980616. - 980714 R.Fisher Minor corrections to Makefile, etc. - 980715 R.Fisher mmx_ok() now prevents optimizer from using - clobbered values. - mmx_ok() now checks if cpuid instruction is - available before trying to use it. - 980726* R.Fisher mm_support() searches for AMD 3DNow, Cyrix - Extended MMX, and standard MMX. It returns a - value which is positive if any of these are - supported, and can be masked with constants to - see which. mmx_ok() is now a call to this - 980726* R.Fisher Added i2r support for shift functions - 980919 R.Fisher Fixed AMD extended feature recognition bug. - 980921 R.Fisher Added definition/check for _MMX_H. - Added "float s[2]" to mmx_t for use with - 3DNow and EMMX. So same mmx_t can be used. - 981013 R.Fisher Fixed cpuid function 1 bug (looked at wrong reg) - Fixed psllq_i2r error in mmxtest.c - - * Unreleased (internal or interim) versions - - Notes: - It appears that the latest gas has the pand problem fixed, therefore - I'll undefine BROKEN_PAND by default. - String compares may be quicker than the multiple test/jumps in vendor - test sequence in mmx_ok(), but I'm not concerned with that right now. - - Acknowledgments: - Jussi Laako for pointing out the errors ultimately found to be - connected to the failure to notify the optimizer of clobbered values. - Roger Hardiman for reminding us that CPUID isn't everywhere, and that - someone may actually try to use this on a machine without CPUID. - Also for suggesting code for checking this. - Robert Dale for pointing out the AMD recognition bug. - Jimmy Mayfield and Carl Witty for pointing out the Intel recognition - bug. - Carl Witty for pointing out the psllq_i2r test bug. -*/ - -#ifndef _MMX_H -#define _MMX_H - -/*#define MMX_TRACE */ - -/* Warning: at this writing, the version of GAS packaged - with most Linux distributions does not handle the - parallel AND operation mnemonic correctly. If the - symbol BROKEN_PAND is defined, a slower alternative - coding will be used. If execution of mmxtest results - in an illegal instruction fault, define this symbol. -*/ -#undef BROKEN_PAND - - -/* The type of an value that fits in an MMX register - (note that long long constant values MUST be suffixed - by LL and unsigned long long values by ULL, lest - they be truncated by the compiler) -*/ -typedef union { - long long q; /* Quadword (64-bit) value */ - unsigned long long uq; /* Unsigned Quadword */ - int d[2]; /* 2 Doubleword (32-bit) values */ - unsigned int ud[2]; /* 2 Unsigned Doubleword */ - short w[4]; /* 4 Word (16-bit) values */ - unsigned short uw[4]; /* 4 Unsigned Word */ - char b[8]; /* 8 Byte (8-bit) values */ - unsigned char ub[8]; /* 8 Unsigned Byte */ - float s[2]; /* Single-precision (32-bit) value */ -} mmx_t; - - -/* Function to test if multimedia instructions are supported... -*/ -inline extern int -mm_support(void) -{ - /* Returns 1 if MMX instructions are supported, - 3 if Cyrix MMX and Extended MMX instructions are supported - 5 if AMD MMX and 3DNow! instructions are supported - 0 if hardware does not support any of these - */ - register int rval = 0; - - __asm__ __volatile__ ( - /* See if CPUID instruction is supported ... */ - /* ... Get copies of EFLAGS into eax and ecx */ - "pushf\n\t" - "popl %%eax\n\t" - "movl %%eax, %%ecx\n\t" - - /* ... Toggle the ID bit in one copy and store */ - /* to the EFLAGS reg */ - "xorl $0x200000, %%eax\n\t" - "push %%eax\n\t" - "popf\n\t" - - /* ... Get the (hopefully modified) EFLAGS */ - "pushf\n\t" - "popl %%eax\n\t" - - /* ... Compare and test result */ - "xorl %%eax, %%ecx\n\t" - "testl $0x200000, %%ecx\n\t" - "jz NotSupported1\n\t" /* Nothing supported */ - - - /* Get standard CPUID information, and - go to a specific vendor section */ - "movl $0, %%eax\n\t" - "cpuid\n\t" - - /* Check for Intel */ - "cmpl $0x756e6547, %%ebx\n\t" - "jne TryAMD\n\t" - "cmpl $0x49656e69, %%edx\n\t" - "jne TryAMD\n\t" - "cmpl $0x6c65746e, %%ecx\n" - "jne TryAMD\n\t" - "jmp Intel\n\t" - - /* Check for AMD */ - "\nTryAMD:\n\t" - "cmpl $0x68747541, %%ebx\n\t" - "jne TryCyrix\n\t" - "cmpl $0x69746e65, %%edx\n\t" - "jne TryCyrix\n\t" - "cmpl $0x444d4163, %%ecx\n" - "jne TryCyrix\n\t" - "jmp AMD\n\t" - - /* Check for Cyrix */ - "\nTryCyrix:\n\t" - "cmpl $0x69727943, %%ebx\n\t" - "jne NotSupported2\n\t" - "cmpl $0x736e4978, %%edx\n\t" - "jne NotSupported3\n\t" - "cmpl $0x64616574, %%ecx\n\t" - "jne NotSupported4\n\t" - /* Drop through to Cyrix... */ - - - /* Cyrix Section */ - /* See if extended CPUID is supported */ - "movl $0x80000000, %%eax\n\t" - "cpuid\n\t" - "cmpl $0x80000000, %%eax\n\t" - "jl MMXtest\n\t" /* Try standard CPUID instead */ - - /* Extended CPUID supported, so get extended features */ - "movl $0x80000001, %%eax\n\t" - "cpuid\n\t" - "testl $0x00800000, %%eax\n\t" /* Test for MMX */ - "jz NotSupported5\n\t" /* MMX not supported */ - "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ - "jnz EMMXSupported\n\t" - "movl $1, %0:\n\n\t" /* MMX Supported */ - "jmp Return\n\n" - "EMMXSupported:\n\t" - "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ - "jmp Return\n\t" - - - /* AMD Section */ - "AMD:\n\t" - - /* See if extended CPUID is supported */ - "movl $0x80000000, %%eax\n\t" - "cpuid\n\t" - "cmpl $0x80000000, %%eax\n\t" - "jl MMXtest\n\t" /* Try standard CPUID instead */ - - /* Extended CPUID supported, so get extended features */ - "movl $0x80000001, %%eax\n\t" - "cpuid\n\t" - "testl $0x00800000, %%edx\n\t" /* Test for MMX */ - "jz NotSupported6\n\t" /* MMX not supported */ - "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ - "jnz ThreeDNowSupported\n\t" - "movl $1, %0:\n\n\t" /* MMX Supported */ - "jmp Return\n\n" - "ThreeDNowSupported:\n\t" - "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ - "jmp Return\n\t" - - - /* Intel Section */ - "Intel:\n\t" - - /* Check for MMX */ - "MMXtest:\n\t" - "movl $1, %%eax\n\t" - "cpuid\n\t" - "testl $0x00800000, %%edx\n\t" /* Test for MMX */ - "jz NotSupported7\n\t" /* MMX Not supported */ - "movl $1, %0:\n\n\t" /* MMX Supported */ - "jmp Return\n\t" - - /* Nothing supported */ - "\nNotSupported1:\n\t" - "#movl $101, %0:\n\n\t" - "\nNotSupported2:\n\t" - "#movl $102, %0:\n\n\t" - "\nNotSupported3:\n\t" - "#movl $103, %0:\n\n\t" - "\nNotSupported4:\n\t" - "#movl $104, %0:\n\n\t" - "\nNotSupported5:\n\t" - "#movl $105, %0:\n\n\t" - "\nNotSupported6:\n\t" - "#movl $106, %0:\n\n\t" - "\nNotSupported7:\n\t" - "#movl $107, %0:\n\n\t" - "movl $0, %0:\n\n\t" - - "Return:\n\t" - : "=a" (rval) - : /* no input */ - : "eax", "ebx", "ecx", "edx" - ); - - /* Return */ - return(rval); -} - -/* Function to test if mmx instructions are supported... -*/ -inline extern int -mmx_ok(void) -{ - /* Returns 1 if MMX instructions are supported, 0 otherwise */ - return ( mm_support() & 0x1 ); -} - - -/* Helper functions for the instruction macros that follow... - (note that memory-to-register, m2r, instructions are nearly - as efficient as register-to-register, r2r, instructions; - however, memory-to-memory instructions are really simulated - as a convenience, and are only 1/3 as efficient) -*/ -#ifdef MMX_TRACE - -/* Include the stuff for printing a trace to stderr... -*/ - -#include - -#define mmx_i2r(op, imm, reg) \ - { \ - mmx_t mmx_trace; \ - mmx_trace = (imm); \ - fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (imm)); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \ - } - -#define mmx_m2r(op, mem, reg) \ - { \ - mmx_t mmx_trace; \ - mmx_trace = (mem); \ - fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem)); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \ - } - -#define mmx_r2m(op, reg, mem) \ - { \ - mmx_t mmx_trace; \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \ - mmx_trace = (mem); \ - fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=X" (mem) \ - : /* nothing */ ); \ - mmx_trace = (mem); \ - fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \ - } - -#define mmx_r2r(op, regs, regd) \ - { \ - mmx_t mmx_trace; \ - __asm__ __volatile__ ("movq %%" #regs ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \ - __asm__ __volatile__ ("movq %%" #regd ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ - __asm__ __volatile__ ("movq %%" #regd ", %0" \ - : "=X" (mmx_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \ - } - -#define mmx_m2m(op, mems, memd) \ - { \ - mmx_t mmx_trace; \ - mmx_trace = (mems); \ - fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \ - mmx_trace = (memd); \ - fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \ - __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ - #op " %1, %%mm0\n\t" \ - "movq %%mm0, %0" \ - : "=X" (memd) \ - : "X" (mems)); \ - mmx_trace = (memd); \ - fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \ - } - -#else - -/* These macros are a lot simpler without the tracing... -*/ - -#define mmx_i2r(op, imm, reg) \ - __asm__ __volatile__ (#op " $" #imm ", %%" #reg \ - : /* nothing */ \ - : /* nothing */); - -#define mmx_m2r(op, mem, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "m" (mem)) - -#define mmx_r2m(op, reg, mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=m" (mem) \ - : /* nothing */ ) - -#define mmx_r2r(op, regs, regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - -#define mmx_m2m(op, mems, memd) \ - __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ - #op " %1, %%mm0\n\t" \ - "movq %%mm0, %0" \ - : "=m" (memd) \ - : "m" (mems)) - -#endif - - -/* 1x64 MOVe Quadword - (this is both a load and a store... - in fact, it is the only way to store) -*/ -#define movq_m2r(var, reg) mmx_m2r(movq, var, reg) -#define movq_r2m(reg, var) mmx_r2m(movq, reg, var) -#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd) -#define movq(vars, vard) \ - __asm__ __volatile__ ("movq %1, %%mm0\n\t" \ - "movq %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* 1x32 MOVe Doubleword - (like movq, this is both load and store... - but is most useful for moving things between - mmx registers and ordinary registers) -*/ -#define movd_m2r(var, reg) mmx_m2r(movd, var, reg) -#define movd_r2m(reg, var) mmx_r2m(movd, reg, var) -#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd) -#define movd(vars, vard) \ - __asm__ __volatile__ ("movd %1, %%mm0\n\t" \ - "movd %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* 2x32, 4x16, and 8x8 Parallel ADDs -*/ -#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg) -#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd) -#define paddd(vars, vard) mmx_m2m(paddd, vars, vard) - -#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg) -#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd) -#define paddw(vars, vard) mmx_m2m(paddw, vars, vard) - -#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg) -#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd) -#define paddb(vars, vard) mmx_m2m(paddb, vars, vard) - - -/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic -*/ -#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg) -#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd) -#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard) - -#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) -#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) -#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard) - - -/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic -*/ -#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg) -#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd) -#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard) - -#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) -#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) -#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard) - - -/* 2x32, 4x16, and 8x8 Parallel SUBs -*/ -#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg) -#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd) -#define psubd(vars, vard) mmx_m2m(psubd, vars, vard) - -#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg) -#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd) -#define psubw(vars, vard) mmx_m2m(psubw, vars, vard) - -#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) -#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) -#define psubb(vars, vard) mmx_m2m(psubb, vars, vard) - - -/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic -*/ -#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg) -#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd) -#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard) - -#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) -#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) -#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard) - - -/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic -*/ -#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg) -#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd) -#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard) - -#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) -#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) -#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard) - - -/* 4x16 Parallel MULs giving Low 4x16 portions of results -*/ -#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg) -#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd) -#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard) - - -/* 4x16 Parallel MULs giving High 4x16 portions of results -*/ -#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg) -#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd) -#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard) - - -/* 4x16->2x32 Parallel Mul-ADD - (muls like pmullw, then adds adjacent 16-bit fields - in the multiply result to make the final 2x32 result) -*/ -#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) -#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) -#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard) - - -/* 1x64 bitwise AND -*/ -#ifdef BROKEN_PAND -#define pand_m2r(var, reg) \ - { \ - mmx_m2r(pandn, (mmx_t) -1LL, reg); \ - mmx_m2r(pandn, var, reg); \ - } -#define pand_r2r(regs, regd) \ - { \ - mmx_m2r(pandn, (mmx_t) -1LL, regd); \ - mmx_r2r(pandn, regs, regd); \ - } -#define pand(vars, vard) \ - { \ - movq_m2r(vard, mm0); \ - mmx_m2r(pandn, (mmx_t) -1LL, mm0); \ - mmx_m2r(pandn, vars, mm0); \ - movq_r2m(mm0, vard); \ - } -#else -#define pand_m2r(var, reg) mmx_m2r(pand, var, reg) -#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd) -#define pand(vars, vard) mmx_m2m(pand, vars, vard) -#endif - - -/* 1x64 bitwise AND with Not the destination -*/ -#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) -#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) -#define pandn(vars, vard) mmx_m2m(pandn, vars, vard) - - -/* 1x64 bitwise OR -*/ -#define por_m2r(var, reg) mmx_m2r(por, var, reg) -#define por_r2r(regs, regd) mmx_r2r(por, regs, regd) -#define por(vars, vard) mmx_m2m(por, vars, vard) - - -/* 1x64 bitwise eXclusive OR -*/ -#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg) -#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd) -#define pxor(vars, vard) mmx_m2m(pxor, vars, vard) - - -/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality - (resulting fields are either 0 or -1) -*/ -#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) -#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) -#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard) - -#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) -#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) -#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard) - -#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) -#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) -#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard) - - -/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than - (resulting fields are either 0 or -1) -*/ -#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) -#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) -#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard) - -#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) -#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) -#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard) - -#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) -#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) -#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard) - - -/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical -*/ -#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg) -#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) -#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) -#define psllq(vars, vard) mmx_m2m(psllq, vars, vard) - -#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg) -#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) -#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) -#define pslld(vars, vard) mmx_m2m(pslld, vars, vard) - -#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg) -#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) -#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) -#define psllw(vars, vard) mmx_m2m(psllw, vars, vard) - - -/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical -*/ -#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg) -#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) -#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) -#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard) - -#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg) -#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) -#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) -#define psrld(vars, vard) mmx_m2m(psrld, vars, vard) - -#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg) -#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) -#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) -#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard) - - -/* 2x32 and 4x16 Parallel Shift Right Arithmetic -*/ -#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg) -#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) -#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) -#define psrad(vars, vard) mmx_m2m(psrad, vars, vard) - -#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg) -#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) -#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) -#define psraw(vars, vard) mmx_m2m(psraw, vars, vard) - - -/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate - (packs source and dest fields into dest in that order) -*/ -#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) -#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) -#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard) - -#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) -#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) -#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard) - - -/* 4x16->8x8 PACK and Unsigned Saturate - (packs source and dest fields into dest in that order) -*/ -#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) -#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) -#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard) - - -/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low - (interleaves low half of dest with low half of source - as padding in each result field) -*/ -#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) -#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) -#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard) - -#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) -#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) -#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard) - -#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) -#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) -#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard) - - -/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High - (interleaves high half of dest with high half of source - as padding in each result field) -*/ -#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) -#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) -#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard) - -#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) -#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) -#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard) - -#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) -#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) -#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard) - - -/* Empty MMx State - (used to clean-up when going from mmx to float use - of the registers that are shared by both; note that - there is no float-to-mmx operation needed, because - only the float tag word info is corruptible) -*/ -#ifdef MMX_TRACE - -#define emms() \ - { \ - fprintf(stderr, "emms()\n"); \ - __asm__ __volatile__ ("emms"); \ - } - -#else - -#define emms() __asm__ __volatile__ ("emms") - -#endif - -#endif diff --git a/gst/deinterlace2/tvtime/plugins.h b/gst/deinterlace2/tvtime/plugins.h deleted file mode 100644 index 8fb01af5..00000000 --- a/gst/deinterlace2/tvtime/plugins.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * GStreamer - * Copyright (C) 2004 Billy Biggs - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs. - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - -#ifndef TVTIME_PLUGINS_H_INCLUDED -#define TVTIME_PLUGINS_H_INCLUDED - -#define GST_TYPE_DEINTERLACE_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ()) -#define GST_TYPE_DEINTERLACE_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ()) -#define GST_TYPE_DEINTERLACE_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ()) -#define GST_TYPE_DEINTERLACE_VFIR (gst_deinterlace_method_vfir_get_type ()) -#define GST_TYPE_DEINTERLACE_LINEAR (gst_deinterlace_method_linear_get_type ()) -#define GST_TYPE_DEINTERLACE_LINEAR_BLEND (gst_deinterlace_method_linear_blend_get_type ()) -#define GST_TYPE_DEINTERLACE_SCALER_BOB (gst_deinterlace_method_scaler_bob_get_type ()) -#define GST_TYPE_DEINTERLACE_WEAVE (gst_deinterlace_method_weave_get_type ()) -#define GST_TYPE_DEINTERLACE_WEAVE_TFF (gst_deinterlace_method_weave_tff_get_type ()) -#define GST_TYPE_DEINTERLACE_WEAVE_BFF (gst_deinterlace_method_weave_bff_get_type ()) - -GType gst_deinterlace_method_tomsmocomp_get_type (void); -GType gst_deinterlace_method_greedy_h_get_type (void); -GType gst_deinterlace_method_greedy_l_get_type (void); -GType gst_deinterlace_method_vfir_get_type (void); - -GType gst_deinterlace_method_linear_get_type (void); -GType gst_deinterlace_method_linear_blend_get_type (void); -GType gst_deinterlace_method_scaler_bob_get_type (void); -GType gst_deinterlace_method_weave_get_type (void); -GType gst_deinterlace_method_weave_tff_get_type (void); -GType gst_deinterlace_method_weave_bff_get_type (void); - -#endif /* TVTIME_PLUGINS_H_INCLUDED */ diff --git a/gst/deinterlace2/tvtime/scalerbob.c b/gst/deinterlace2/tvtime/scalerbob.c deleted file mode 100644 index a37792ab..00000000 --- a/gst/deinterlace2/tvtime/scalerbob.c +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Double lines - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB (gst_deinterlace_method_scaler_bob_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_SCALER_BOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB)) -#define GST_IS_DEINTERLACE_METHOD_SCALER_BOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB)) -#define GST_DEINTERLACE_METHOD_SCALER_BOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB, GstDeinterlaceMethodScalerBobClass)) -#define GST_DEINTERLACE_METHOD_SCALER_BOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB, GstDeinterlaceMethodScalerBob)) -#define GST_DEINTERLACE_METHOD_SCALER_BOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_SCALER_BOB, GstDeinterlaceMethodScalerBobClass)) -#define GST_DEINTERLACE_METHOD_SCALER_BOB_CAST(obj) ((GstDeinterlaceMethodScalerBob*)(obj)) - -GType gst_deinterlace_method_scaler_bob_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodScalerBob; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodScalerBobClass; - - -static void -deinterlace_scanline_scaler_bob (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->t0, parent->row_stride); -} - -G_DEFINE_TYPE (GstDeinterlaceMethodScalerBob, gst_deinterlace_method_scaler_bob, - GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void -gst_deinterlace_method_scaler_bob_class_init (GstDeinterlaceMethodScalerBobClass - * klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; - - dim_class->fields_required = 1; - dim_class->name = "Double lines"; - dim_class->nick = "scalerbob"; - dim_class->latency = 0; - - dism_class->interpolate_scanline = deinterlace_scanline_scaler_bob; -} - -static void -gst_deinterlace_method_scaler_bob_init (GstDeinterlaceMethodScalerBob * self) -{ -} diff --git a/gst/deinterlace2/tvtime/sse.h b/gst/deinterlace2/tvtime/sse.h deleted file mode 100644 index 2e00ee0c..00000000 --- a/gst/deinterlace2/tvtime/sse.h +++ /dev/null @@ -1,992 +0,0 @@ -/* sse.h - - Streaming SIMD Extenstions (a.k.a. Katmai New Instructions) - GCC interface library for IA32. - - To use this library, simply include this header file - and compile with GCC. You MUST have inlining enabled - in order for sse_ok() to work; this can be done by - simply using -O on the GCC command line. - - Compiling with -DSSE_TRACE will cause detailed trace - output to be sent to stderr for each sse operation. - This adds lots of code, and obviously slows execution to - a crawl, but can be very useful for debugging. - - THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT - LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR ANY PARTICULAR PURPOSE. - - 1999 by R. Fisher - Based on libmmx by H. Dietz and R. Fisher - - Notes: - This is still extremely alpha. - Because this library depends on an assembler which understands the - SSE opcodes, you probably won't be able to use this yet. - For now, do not use TRACE versions. These both make use - of the MMX registers, not the SSE registers. This will be resolved - at a later date. - ToDo: - Rewrite TRACE macros - Major Debugging Work -*/ - -#ifndef _SSE_H -#define _SSE_H - - - -/* The type of an value that fits in an SSE register - (note that long long constant values MUST be suffixed - by LL and unsigned long long values by ULL, lest - they be truncated by the compiler) -*/ -typedef union { - float sf[4]; /* Single-precision (32-bit) value */ -} __attribute__ ((aligned (16))) sse_t; /* On a 16 byte (128-bit) boundary */ - - -#if 0 -/* Function to test if multimedia instructions are supported... -*/ -inline extern int -mm_support(void) -{ - /* Returns 1 if MMX instructions are supported, - 3 if Cyrix MMX and Extended MMX instructions are supported - 5 if AMD MMX and 3DNow! instructions are supported - 9 if MMX and SSE instructions are supported - 0 if hardware does not support any of these - */ - register int rval = 0; - - __asm__ __volatile__ ( - /* See if CPUID instruction is supported ... */ - /* ... Get copies of EFLAGS into eax and ecx */ - "pushf\n\t" - "popl %%eax\n\t" - "movl %%eax, %%ecx\n\t" - - /* ... Toggle the ID bit in one copy and store */ - /* to the EFLAGS reg */ - "xorl $0x200000, %%eax\n\t" - "push %%eax\n\t" - "popf\n\t" - - /* ... Get the (hopefully modified) EFLAGS */ - "pushf\n\t" - "popl %%eax\n\t" - - /* ... Compare and test result */ - "xorl %%eax, %%ecx\n\t" - "testl $0x200000, %%ecx\n\t" - "jz NotSupported1\n\t" /* CPUID not supported */ - - - /* Get standard CPUID information, and - go to a specific vendor section */ - "movl $0, %%eax\n\t" - "cpuid\n\t" - - /* Check for Intel */ - "cmpl $0x756e6547, %%ebx\n\t" - "jne TryAMD\n\t" - "cmpl $0x49656e69, %%edx\n\t" - "jne TryAMD\n\t" - "cmpl $0x6c65746e, %%ecx\n" - "jne TryAMD\n\t" - "jmp Intel\n\t" - - /* Check for AMD */ - "\nTryAMD:\n\t" - "cmpl $0x68747541, %%ebx\n\t" - "jne TryCyrix\n\t" - "cmpl $0x69746e65, %%edx\n\t" - "jne TryCyrix\n\t" - "cmpl $0x444d4163, %%ecx\n" - "jne TryCyrix\n\t" - "jmp AMD\n\t" - - /* Check for Cyrix */ - "\nTryCyrix:\n\t" - "cmpl $0x69727943, %%ebx\n\t" - "jne NotSupported2\n\t" - "cmpl $0x736e4978, %%edx\n\t" - "jne NotSupported3\n\t" - "cmpl $0x64616574, %%ecx\n\t" - "jne NotSupported4\n\t" - /* Drop through to Cyrix... */ - - - /* Cyrix Section */ - /* See if extended CPUID level 80000001 is supported */ - /* The value of CPUID/80000001 for the 6x86MX is undefined - according to the Cyrix CPU Detection Guide (Preliminary - Rev. 1.01 table 1), so we'll check the value of eax for - CPUID/0 to see if standard CPUID level 2 is supported. - According to the table, the only CPU which supports level - 2 is also the only one which supports extended CPUID levels. - */ - "cmpl $0x2, %%eax\n\t" - "jne MMXtest\n\t" /* Use standard CPUID instead */ - - /* Extended CPUID supported (in theory), so get extended - features */ - "movl $0x80000001, %%eax\n\t" - "cpuid\n\t" - "testl $0x00800000, %%eax\n\t" /* Test for MMX */ - "jz NotSupported5\n\t" /* MMX not supported */ - "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ - "jnz EMMXSupported\n\t" - "movl $1, %0:\n\n\t" /* MMX Supported */ - "jmp Return\n\n" - "EMMXSupported:\n\t" - "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ - "jmp Return\n\t" - - - /* AMD Section */ - "AMD:\n\t" - - /* See if extended CPUID is supported */ - "movl $0x80000000, %%eax\n\t" - "cpuid\n\t" - "cmpl $0x80000000, %%eax\n\t" - "jl MMXtest\n\t" /* Use standard CPUID instead */ - - /* Extended CPUID supported, so get extended features */ - "movl $0x80000001, %%eax\n\t" - "cpuid\n\t" - "testl $0x00800000, %%edx\n\t" /* Test for MMX */ - "jz NotSupported6\n\t" /* MMX not supported */ - "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ - "jnz ThreeDNowSupported\n\t" - "movl $1, %0:\n\n\t" /* MMX Supported */ - "jmp Return\n\n" - "ThreeDNowSupported:\n\t" - "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ - "jmp Return\n\t" - - - /* Intel Section */ - "Intel:\n\t" - - /* Check for SSE */ - "SSEtest:\n\t" - "movl $1, %%eax\n\t" - "cpuid\n\t" - "testl $0x02000000, %%edx\n\t" /* Test for SSE */ - "jz MMXtest\n\t" /* SSE Not supported */ - "movl $9, %0:\n\n\t" /* SSE Supported */ - "jmp Return\n\t" - - /* Check for MMX */ - "MMXtest:\n\t" - "movl $1, %%eax\n\t" - "cpuid\n\t" - "testl $0x00800000, %%edx\n\t" /* Test for MMX */ - "jz NotSupported7\n\t" /* MMX Not supported */ - "movl $1, %0:\n\n\t" /* MMX Supported */ - "jmp Return\n\t" - - /* Nothing supported */ - "\nNotSupported1:\n\t" - "#movl $101, %0:\n\n\t" - "\nNotSupported2:\n\t" - "#movl $102, %0:\n\n\t" - "\nNotSupported3:\n\t" - "#movl $103, %0:\n\n\t" - "\nNotSupported4:\n\t" - "#movl $104, %0:\n\n\t" - "\nNotSupported5:\n\t" - "#movl $105, %0:\n\n\t" - "\nNotSupported6:\n\t" - "#movl $106, %0:\n\n\t" - "\nNotSupported7:\n\t" - "#movl $107, %0:\n\n\t" - "movl $0, %0:\n\n\t" - - "Return:\n\t" - : "=a" (rval) - : /* no input */ - : "eax", "ebx", "ecx", "edx" - ); - - /* Return */ - return(rval); -} - -/* Function to test if sse instructions are supported... -*/ -inline extern int -sse_ok(void) -{ - /* Returns 1 if SSE instructions are supported, 0 otherwise */ - return ( (mm_support() & 0x8) >> 3 ); -} -#endif - - - -/* Helper functions for the instruction macros that follow... - (note that memory-to-register, m2r, instructions are nearly - as efficient as register-to-register, r2r, instructions; - however, memory-to-memory instructions are really simulated - as a convenience, and are only 1/3 as efficient) -*/ -#ifdef SSE_TRACE - -/* Include the stuff for printing a trace to stderr... -*/ - -#include - -#define sse_i2r(op, imm, reg) \ - { \ - sse_t sse_trace; \ - sse_trace.uq = (imm); \ - fprintf(stderr, #op "_i2r(" #imm "=0x%08x%08x, ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%08x%08x) => ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (imm)); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%08x%08x\n", \ - sse_trace.d[1], sse_trace.d[0]); \ - } - -#define sse_m2r(op, mem, reg) \ - { \ - sse_t sse_trace; \ - sse_trace = (mem); \ - fprintf(stderr, #op "_m2r(" #mem "=0x%08x%08x, ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%08x%08x) => ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem)); \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #reg "=0x%08x%08x\n", \ - sse_trace.d[1], sse_trace.d[0]); \ - } - -#define sse_r2m(op, reg, mem) \ - { \ - sse_t sse_trace; \ - __asm__ __volatile__ ("movq %%" #reg ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #op "_r2m(" #reg "=0x%08x%08x, ", \ - sse_trace.d[1], sse_trace.d[0]); \ - sse_trace = (mem); \ - fprintf(stderr, #mem "=0x%08x%08x) => ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=X" (mem) \ - : /* nothing */ ); \ - sse_trace = (mem); \ - fprintf(stderr, #mem "=0x%08x%08x\n", \ - sse_trace.d[1], sse_trace.d[0]); \ - } - -#define sse_r2r(op, regs, regd) \ - { \ - sse_t sse_trace; \ - __asm__ __volatile__ ("movq %%" #regs ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #op "_r2r(" #regs "=0x%08x%08x, ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ ("movq %%" #regd ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #regd "=0x%08x%08x) => ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ - __asm__ __volatile__ ("movq %%" #regd ", %0" \ - : "=X" (sse_trace) \ - : /* nothing */ ); \ - fprintf(stderr, #regd "=0x%08x%08x\n", \ - sse_trace.d[1], sse_trace.d[0]); \ - } - -#define sse_m2m(op, mems, memd) \ - { \ - sse_t sse_trace; \ - sse_trace = (mems); \ - fprintf(stderr, #op "_m2m(" #mems "=0x%08x%08x, ", \ - sse_trace.d[1], sse_trace.d[0]); \ - sse_trace = (memd); \ - fprintf(stderr, #memd "=0x%08x%08x) => ", \ - sse_trace.d[1], sse_trace.d[0]); \ - __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ - #op " %1, %%mm0\n\t" \ - "movq %%mm0, %0" \ - : "=X" (memd) \ - : "X" (mems)); \ - sse_trace = (memd); \ - fprintf(stderr, #memd "=0x%08x%08x\n", \ - sse_trace.d[1], sse_trace.d[0]); \ - } - -#else - -/* These macros are a lot simpler without the tracing... -*/ - -#define sse_i2r(op, imm, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2r(op, mem, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem)) - -#define sse_r2m(op, reg, mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=X" (mem) \ - : /* nothing */ ) - -#define sse_r2r(op, regs, regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - -#define sse_r2ri(op, regs, regd, imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "X" (imm) ) - -/* Load data from mems to xmmreg, operate on xmmreg, and store data to memd */ -#define sse_m2m(op, mems, memd, xmmreg) \ - __asm__ __volatile__ ("movups %0, %%xmm0\n\t" \ - #op " %1, %%xmm0\n\t" \ - "movups %%mm0, %0" \ - : "=X" (memd) \ - : "X" (mems)) - -#define sse_m2ri(op, mem, reg, subop) \ - __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ - : /* nothing */ \ - : "X" (mem)) - -#define sse_m2mi(op, mems, memd, xmmreg, subop) \ - __asm__ __volatile__ ("movups %0, %%xmm0\n\t" \ - #op " %1, %%xmm0, " #subop "\n\t" \ - "movups %%mm0, %0" \ - : "=X" (memd) \ - : "X" (mems)) -#endif - - - - -/* 1x128 MOVe Aligned four Packed Single-fp -*/ -#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) -#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) -#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) -#define movaps(vars, vard) \ - __asm__ __volatile__ ("movaps %1, %%mm0\n\t" \ - "movaps %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* 1x128 MOVe aligned Non-Temporal four Packed Single-fp -*/ -#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) - - -/* 1x64 MOVe Non-Temporal Quadword -*/ -#define movntq_r2m(mmreg, var) sse_r2m(movntq, mmreg, var) - - -/* 1x128 MOVe Unaligned four Packed Single-fp -*/ -#define movups_m2r(var, reg) sse_m2r(movups, var, reg) -#define movups_r2m(reg, var) sse_r2m(movups, reg, var) -#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) -#define movups(vars, vard) \ - __asm__ __volatile__ ("movups %1, %%mm0\n\t" \ - "movups %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* MOVe High to Low Packed Single-fp - high half of 4x32f (x) -> low half of 4x32f (y) -*/ -#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) - - -/* MOVe Low to High Packed Single-fp - low half of 4x32f (x) -> high half of 4x32f (y) -*/ -#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) - - -/* MOVe High Packed Single-fp - 2x32f -> high half of 4x32f -*/ -#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) -#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) -#define movhps(vars, vard) \ - __asm__ __volatile__ ("movhps %1, %%mm0\n\t" \ - "movhps %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* MOVe Low Packed Single-fp - 2x32f -> low half of 4x32f -*/ -#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) -#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) -#define movlps(vars, vard) \ - __asm__ __volatile__ ("movlps %1, %%mm0\n\t" \ - "movlps %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* MOVe Scalar Single-fp - lowest field of 4x32f (x) -> lowest field of 4x32f (y) -*/ -#define movss_m2r(var, reg) sse_m2r(movss, var, reg) -#define movss_r2m(reg, var) sse_r2m(movss, reg, var) -#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) -#define movss(vars, vard) \ - __asm__ __volatile__ ("movss %1, %%mm0\n\t" \ - "movss %%mm0, %0" \ - : "=X" (vard) \ - : "X" (vars)) - - -/* 4x16 Packed SHUFfle Word -*/ -#define pshufw_m2r(var, reg, index) sse_m2ri(pshufw, var, reg, index) -#define pshufw_r2r(regs, regd, index) sse_r2ri(pshufw, regs, regd, index) - - -/* 1x128 SHUFfle Packed Single-fp -*/ -#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) -#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) - - -/* ConVerT Packed signed Int32 to(2) Packed Single-fp -*/ -#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) -#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) - - -/* ConVerT Packed Single-fp to(2) Packed signed Int32 -*/ -#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) -#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) - - -/* ConVerT with Truncate Packed Single-fp to(2) Packed Int32 -*/ -#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) -#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) - - -/* ConVerT Signed Int32 to(2) Single-fp (Scalar) -*/ -#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) -#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) - - -/* ConVerT Scalar Single-fp to(2) Signed Int32 -*/ -#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - - -/* ConVerT with Truncate Scalar Single-fp to(2) Signed Int32 -*/ -#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - - -/* Parallel EXTRact Word from 4x16 -*/ -#define pextrw_r2r(mmreg, reg, field) sse_r2ri(pextrw, mmreg, reg, field) - - -/* Parallel INSeRt Word from 4x16 -*/ -#define pinsrw_r2r(reg, mmreg, field) sse_r2ri(pinsrw, reg, mmreg, field) - - - -/* MOVe MaSK from Packed Single-fp -*/ -#ifdef SSE_TRACE - #define movmskps(xmmreg, reg) \ - { \ - fprintf(stderr, "movmskps()\n"); \ - __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) \ - } -#else - #define movmskps(xmmreg, reg) \ - __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) -#endif - - -/* Parallel MOVe MaSK from mmx reg to 32-bit reg -*/ -#ifdef SSE_TRACE - #define pmovmskb(mmreg, reg) \ - { \ - fprintf(stderr, "movmskps()\n"); \ - __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) \ - } -#else - #define pmovmskb(mmreg, reg) \ - __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) -#endif - - -/* MASKed MOVe from 8x8 to memory pointed to by (e)di register -*/ -#define maskmovq(mmregs, fieldreg) sse_r2ri(maskmovq, mmregs, fieldreg) - - - - -/* 4x32f Parallel ADDs -*/ -#define addps_m2r(var, reg) sse_m2r(addps, var, reg) -#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) -#define addps(vars, vard, xmmreg) sse_m2m(addps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel ADDs -*/ -#define addss_m2r(var, reg) sse_m2r(addss, var, reg) -#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) -#define addss(vars, vard, xmmreg) sse_m2m(addss, vars, vard, xmmreg) - - -/* 4x32f Parallel SUBs -*/ -#define subps_m2r(var, reg) sse_m2r(subps, var, reg) -#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) -#define subps(vars, vard, xmmreg) sse_m2m(subps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel SUBs -*/ -#define subss_m2r(var, reg) sse_m2r(subss, var, reg) -#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) -#define subss(vars, vard, xmmreg) sse_m2m(subss, vars, vard, xmmreg) - - -/* 8x8u -> 4x16u Packed Sum of Absolute Differences -*/ -#define psadbw_m2r(var, reg) sse_m2r(psadbw, var, reg) -#define psadbw_r2r(regs, regd) sse_r2r(psadbw, regs, regd) -#define psadbw(vars, vard, mmreg) sse_m2m(psadbw, vars, vard, mmreg) - - -/* 4x16u Parallel MUL High Unsigned -*/ -#define pmulhuw_m2r(var, reg) sse_m2r(pmulhuw, var, reg) -#define pmulhuw_r2r(regs, regd) sse_r2r(pmulhuw, regs, regd) -#define pmulhuw(vars, vard, mmreg) sse_m2m(pmulhuw, vars, vard, mmreg) - - -/* 4x32f Parallel MULs -*/ -#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) -#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) -#define mulps(vars, vard, xmmreg) sse_m2m(mulps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel MULs -*/ -#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) -#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) -#define mulss(vars, vard, xmmreg) sse_m2m(mulss, vars, vard, xmmreg) - - -/* 4x32f Parallel DIVs -*/ -#define divps_m2r(var, reg) sse_m2r(divps, var, reg) -#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) -#define divps(vars, vard, xmmreg) sse_m2m(divps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel DIVs -*/ -#define divss_m2r(var, reg) sse_m2r(divss, var, reg) -#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) -#define divss(vars, vard, xmmreg) sse_m2m(divss, vars, vard, xmmreg) - - -/* 4x32f Parallel Reciprocals -*/ -#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) -#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) -#define rcpps(vars, vard, xmmreg) sse_m2m(rcpps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel Reciprocals -*/ -#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) -#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) -#define rcpss(vars, vard, xmmreg) sse_m2m(rcpss, vars, vard, xmmreg) - - -/* 4x32f Parallel Square Root of Reciprocals -*/ -#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) -#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) -#define rsqrtps(vars, vard, xmmreg) sse_m2m(rsqrtps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel Square Root of Reciprocals -*/ -#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) -#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) -#define rsqrtss(vars, vard, xmmreg) sse_m2m(rsqrtss, vars, vard, xmmreg) - - -/* 4x32f Parallel Square Roots -*/ -#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) -#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) -#define sqrtps(vars, vard, xmmreg) sse_m2m(sqrtps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel Square Roots -*/ -#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) -#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) -#define sqrtss(vars, vard, xmmreg) sse_m2m(sqrtss, vars, vard, xmmreg) - - -/* 8x8u and 4x16u Parallel AVeraGe -*/ -#define pavgb_m2r(var, reg) sse_m2r(pavgb, var, reg) -#define pavgb_r2r(regs, regd) sse_r2r(pavgb, regs, regd) -#define pavgb(vars, vard, mmreg) sse_m2m(pavgb, vars, vard, mmreg) - -#define pavgw_m2r(var, reg) sse_m2r(pavgw, var, reg) -#define pavgw_r2r(regs, regd) sse_r2r(pavgw, regs, regd) -#define pavgw(vars, vard, mmreg) sse_m2m(pavgw, vars, vard, mmreg) - - -/* 1x128 bitwise AND -*/ -#define andps_m2r(var, reg) sse_m2r(andps, var, reg) -#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) -#define andps(vars, vard, xmmreg) sse_m2m(andps, vars, vard, xmmreg) - - -/* 1x128 bitwise AND with Not the destination -*/ -#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) -#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) -#define andnps(vars, vard, xmmreg) sse_m2m(andnps, vars, vard, xmmreg) - - -/* 1x128 bitwise OR -*/ -#define orps_m2r(var, reg) sse_m2r(orps, var, reg) -#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) -#define orps(vars, vard, xmmreg) sse_m2m(orps, vars, vard, xmmreg) - - -/* 1x128 bitwise eXclusive OR -*/ -#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) -#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) -#define xorps(vars, vard, xmmreg) sse_m2m(xorps, vars, vard, xmmreg) - - -/* 8x8u, 4x16, and 4x32f Parallel Maximum -*/ -#define pmaxub_m2r(var, reg) sse_m2r(pmaxub, var, reg) -#define pmaxub_r2r(regs, regd) sse_r2r(pmaxub, regs, regd) -#define pmaxub(vars, vard, mmreg) sse_m2m(pmaxub, vars, vard, mmreg) - -#define pmaxsw_m2r(var, reg) sse_m2r(pmaxsw, var, reg) -#define pmaxsw_r2r(regs, regd) sse_r2r(pmaxsw, regs, regd) -#define pmaxsw(vars, vard, mmreg) sse_m2m(pmaxsw, vars, vard, mmreg) - -#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) -#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) -#define maxps(vars, vard, xmmreg) sse_m2m(maxps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel Maximum -*/ -#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) -#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) -#define maxss(vars, vard, xmmreg) sse_m2m(maxss, vars, vard, xmmreg) - - -/* 8x8u, 4x16, and 4x32f Parallel Minimum -*/ -#define pminub_m2r(var, reg) sse_m2r(pminub, var, reg) -#define pminub_r2r(regs, regd) sse_r2r(pminub, regs, regd) -#define pminub(vars, vard, mmreg) sse_m2m(pminub, vars, vard, mmreg) - -#define pminsw_m2r(var, reg) sse_m2r(pminsw, var, reg) -#define pminsw_r2r(regs, regd) sse_r2r(pminsw, regs, regd) -#define pminsw(vars, vard, mmreg) sse_m2m(pminsw, vars, vard, mmreg) - -#define minps_m2r(var, reg) sse_m2r(minps, var, reg) -#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) -#define minps(vars, vard, xmmreg) sse_m2m(minps, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Parallel Minimum -*/ -#define minss_m2r(var, reg) sse_m2r(minss, var, reg) -#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) -#define minss(vars, vard, xmmreg) sse_m2m(minss, vars, vard, xmmreg) - - -/* 4x32f Parallel CoMPares - (resulting fields are either 0 or -1) -*/ -#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) -#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) -#define cmpps(vars, vard, op, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, op) - -#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) -#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) -#define cmpeqps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 0) - -#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) -#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) -#define cmpltps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 1) - -#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) -#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) -#define cmpleps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 2) - -#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) -#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) -#define cmpunordps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 3) - -#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) -#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) -#define cmpneqps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 4) - -#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) -#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) -#define cmpnltps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 5) - -#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) -#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) -#define cmpnleps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 6) - -#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) -#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) -#define cmpordps(vars, vard, xmmreg) sse_m2mi(cmpps, vars, vard, xmmreg, 7) - - -/* Lowest Field of 4x32f Parallel CoMPares - (resulting fields are either 0 or -1) -*/ -#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) -#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) -#define cmpss(vars, vard, op, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, op) - -#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) -#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) -#define cmpeqss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 0) - -#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) -#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) -#define cmpltss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 1) - -#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) -#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) -#define cmpless(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 2) - -#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) -#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) -#define cmpunordss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 3) - -#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) -#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) -#define cmpneqss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 4) - -#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) -#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) -#define cmpnltss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 5) - -#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) -#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) -#define cmpnless(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 6) - -#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) -#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) -#define cmpordss(vars, vard, xmmreg) sse_m2mi(cmpss, vars, vard, xmmreg, 7) - - -/* Lowest Field of 4x32f Parallel CoMPares to set EFLAGS - (resulting fields are either 0 or -1) -*/ -#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) -#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) -#define comiss(vars, vard, xmmreg) sse_m2m(comiss, vars, vard, xmmreg) - - -/* Lowest Field of 4x32f Unordered Parallel CoMPares to set EFLAGS - (resulting fields are either 0 or -1) -*/ -#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) -#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) -#define ucomiss(vars, vard, xmmreg) sse_m2m(ucomiss, vars, vard, xmmreg) - - -/* 2-(4x32f) -> 4x32f UNPaCK Low Packed Single-fp - (interleaves low half of dest with low half of source - as padding in each result field) -*/ -#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) -#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) - - -/* 2-(4x32f) -> 4x32f UNPaCK High Packed Single-fp - (interleaves high half of dest with high half of source - as padding in each result field) -*/ -#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) -#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) - - - -/* Fp and mmX ReSTORe state -*/ -#ifdef SSE_TRACE - #define fxrstor(mem) \ - { \ - fprintf(stderr, "fxrstor()\n"); \ - __asm__ __volatile__ ("fxrstor %0" \ - : /* nothing */ \ - : "X" (mem)) \ - } -#else - #define fxrstor(mem) \ - __asm__ __volatile__ ("fxrstor %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif - - -/* Fp and mmX SAVE state -*/ -#ifdef SSE_TRACE - #define fxsave(mem) \ - { \ - fprintf(stderr, "fxsave()\n"); \ - __asm__ __volatile__ ("fxsave %0" \ - : /* nothing */ \ - : "X" (mem)) \ - } -#else - #define fxsave(mem) \ - __asm__ __volatile__ ("fxsave %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif - - -/* STore streaMing simd eXtensions Control/Status Register -*/ -#ifdef SSE_TRACE - #define stmxcsr(mem) \ - { \ - fprintf(stderr, "stmxcsr()\n"); \ - __asm__ __volatile__ ("stmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) \ - } -#else - #define stmxcsr(mem) \ - __asm__ __volatile__ ("stmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif - - -/* LoaD streaMing simd eXtensions Control/Status Register -*/ -#ifdef SSE_TRACE - #define ldmxcsr(mem) \ - { \ - fprintf(stderr, "ldmxcsr()\n"); \ - __asm__ __volatile__ ("ldmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) \ - } -#else - #define ldmxcsr(mem) \ - __asm__ __volatile__ ("ldmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif - - -/* Store FENCE - enforce ordering of stores before fence vs. stores - occuring after fence in source code. -*/ -#ifdef SSE_TRACE - #define sfence() \ - { \ - fprintf(stderr, "sfence()\n"); \ - __asm__ __volatile__ ("sfence\n\t") \ - } -#else - #define sfence() \ - __asm__ __volatile__ ("sfence\n\t") -#endif - - -/* PREFETCH data using T0, T1, T2, or NTA hint - T0 = Prefetch into all cache levels - T1 = Prefetch into all cache levels except 0th level - T2 = Prefetch into all cache levels except 0th and 1st levels - NTA = Prefetch data into non-temporal cache structure -*/ -#ifdef SSE_TRACE -#else - #define prefetch(mem, hint) \ - __asm__ __volatile__ ("prefetch" #hint " %0" \ - : /* nothing */ \ - : "X" (mem)) - - #define prefetcht0(mem) prefetch(mem, t0) - #define prefetcht1(mem) prefetch(mem, t1) - #define prefetcht2(mem) prefetch(mem, t2) - #define prefetchnta(mem) prefetch(mem, nta) -#endif - - - -#endif diff --git a/gst/deinterlace2/tvtime/tomsmocomp.c b/gst/deinterlace2/tvtime/tomsmocomp.c deleted file mode 100644 index 64e78c5b..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp.c +++ /dev/null @@ -1,211 +0,0 @@ -/** - * Copyright (C) 2004 Billy Biggs - * Copyright (C) 2008 Sebastian Dröge - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include "_stdint.h" -#include - -#include "gst/gst.h" -#include "gstdeinterlace2.h" -#include "plugins.h" - -#define GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP)) -#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP)) -#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass)) -#define GST_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoComp)) -#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass)) -#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CAST(obj) ((GstDeinterlaceMethodTomsMoComp*)(obj)) - -GType gst_deinterlace_method_tomsmocomp_get_type (void); - -typedef struct -{ - GstDeinterlaceMethod parent; - - guint search_effort; - gboolean strange_bob; -} GstDeinterlaceMethodTomsMoComp; - -typedef struct -{ - GstDeinterlaceMethodClass parent_class; -} GstDeinterlaceMethodTomsMoCompClass; - -static int -Fieldcopy (void *dest, const void *src, size_t count, - int rows, int dst_pitch, int src_pitch) -{ - unsigned char *pDest = (unsigned char *) dest; - unsigned char *pSrc = (unsigned char *) src; - - int i; - - for (i = 0; i < rows; i++) { - oil_memcpy (pDest, pSrc, count); - pSrc += src_pitch; - pDest += dst_pitch; - } - return 0; -} - -#define USE_FOR_DSCALER - -#define IS_C -#define SIMD_TYPE C -#define FUNCT_NAME tomsmocompDScaler_C -#include "tomsmocomp/TomsMoCompAll.inc" -#undef IS_C -#undef SIMD_TYPE -#undef FUNCT_NAME - -#ifdef BUILD_X86_ASM - -#include "tomsmocomp/tomsmocompmacros.h" -#include "x86-64_macros.inc" - -#define IS_MMX -#define SIMD_TYPE MMX -#define FUNCT_NAME tomsmocompDScaler_MMX -#include "tomsmocomp/TomsMoCompAll.inc" -#undef IS_MMX -#undef SIMD_TYPE -#undef FUNCT_NAME - -#define IS_3DNOW -#define SIMD_TYPE 3DNOW -#define FUNCT_NAME tomsmocompDScaler_3DNOW -#include "tomsmocomp/TomsMoCompAll.inc" -#undef IS_3DNOW -#undef SIMD_TYPE -#undef FUNCT_NAME - -#define IS_MMXEXT -#define SIMD_TYPE MMXEXT -#define FUNCT_NAME tomsmocompDScaler_MMXEXT -#include "tomsmocomp/TomsMoCompAll.inc" -#undef IS_MMXEXT -#undef SIMD_TYPE -#undef FUNCT_NAME - -#endif - -G_DEFINE_TYPE (GstDeinterlaceMethodTomsMoComp, - gst_deinterlace_method_tomsmocomp, GST_TYPE_DEINTERLACE_METHOD); - -enum -{ - ARG_0, - ARG_SEARCH_EFFORT, - ARG_STRANGE_BOB -}; - -static void -gst_deinterlace_method_tomsmocomp_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstDeinterlaceMethodTomsMoComp *self = - GST_DEINTERLACE_METHOD_TOMSMOCOMP (object); - - switch (prop_id) { - case ARG_SEARCH_EFFORT: - self->search_effort = g_value_get_uint (value); - break; - case ARG_STRANGE_BOB: - self->strange_bob = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gst_deinterlace_method_tomsmocomp_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstDeinterlaceMethodTomsMoComp *self = - GST_DEINTERLACE_METHOD_TOMSMOCOMP (object); - - switch (prop_id) { - case ARG_SEARCH_EFFORT: - g_value_set_uint (value, self->search_effort); - break; - case ARG_STRANGE_BOB: - g_value_set_boolean (value, self->strange_bob); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void - gst_deinterlace_method_tomsmocomp_class_init - (GstDeinterlaceMethodTomsMoCompClass * klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GObjectClass *gobject_class = (GObjectClass *) klass; -#ifdef BUILD_X86_ASM - guint cpu_flags = oil_cpu_get_flags (); -#endif - - gobject_class->set_property = gst_deinterlace_method_tomsmocomp_set_property; - gobject_class->get_property = gst_deinterlace_method_tomsmocomp_get_property; - - g_object_class_install_property (gobject_class, ARG_SEARCH_EFFORT, - g_param_spec_uint ("search-effort", - "Search Effort", - "Search Effort", 0, 27, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - g_object_class_install_property (gobject_class, ARG_STRANGE_BOB, - g_param_spec_boolean ("strange-bob", - "Strange Bob", - "Use strange bob", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) - ); - - dim_class->fields_required = 4; - dim_class->name = "Motion Adaptive: Motion Search"; - dim_class->nick = "tomsmocomp"; - dim_class->latency = 1; - -#ifdef BUILD_X86_ASM - if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) { - dim_class->deinterlace_frame = tomsmocompDScaler_MMXEXT; - } else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) { - dim_class->deinterlace_frame = tomsmocompDScaler_3DNOW; - } else if (cpu_flags & OIL_IMPL_FLAG_MMX) { - dim_class->deinterlace_frame = tomsmocompDScaler_MMX; - } else { - dim_class->deinterlace_frame = tomsmocompDScaler_C; - } -#else - dim_class->deinterlace_frame = tomsmocompDScaler_C; -#endif -} - -static void -gst_deinterlace_method_tomsmocomp_init (GstDeinterlaceMethodTomsMoComp * self) -{ - self->search_effort = 5; - self->strange_bob = FALSE; -} diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoop0A.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoop0A.inc deleted file mode 100644 index b1d9aeca..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoop0A.inc +++ /dev/null @@ -1,15 +0,0 @@ -// -*- c++ -*- - -// Searches just the center pixel, in both the old -// and new fields, but takes averages. This is an even -// pixel address. Any chroma match will be used. (YUY2) -// We best like finding 0 motion so we will bias everything we found previously -// up by a little, and adjust later - -#ifdef IS_SSE2 - "paddusb "_ONES", %%xmm7\n\t" // bias toward no motion -#else - "paddusb "_ONES", %%mm7\n\t" // bias toward no motion -#endif - - MERGE4PIXavg("(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")") // center, in old and new diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopBottom.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopBottom.inc deleted file mode 100644 index e1560353..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopBottom.inc +++ /dev/null @@ -1,174 +0,0 @@ -// -*- c++ -*- - -// Version for non-SSE2 - -#ifndef IS_C - -#ifdef SKIP_SEARCH - "movq %%mm6, %%mm0\n\t" // just use the results of our wierd bob -#else - - - // JA 9/Dec/2002 - // failed experiment - // but leave in placeholder for me to play about -#ifdef DONT_USE_STRANGE_BOB - // Use the best weave if diffs less than 10 as that - // means the image is still or moving cleanly - // if there is motion we will clip which will catch anything - "psubusb "_FOURS", %%mm7\n\t" // sets bits to zero if weave diff < 4 - "pxor %%mm0, %%mm0\n\t" - "pcmpeqb %%mm0, %%mm7\n\t" // all ff where weave better, else 00 - "pcmpeqb %%mm7, %%mm0\n\t" // all ff where bob better, else 00 - "pand %%mm6, %%mm0\n\t" // use bob for these pixel values - "pand %%mm5, %%mm7\n\t" // use weave for these - "por %%mm7, %%mm0\n\t" // combine both -#else - // Use the better of bob or weave - // pminub mm4, TENS // the most we care about - V_PMINUB ("%%mm4", _TENS, "%%mm0") // the most we care about - - "psubusb %%mm4, %%mm7\n\t" // foregive that much from weave est? - "psubusb "_FOURS", %%mm7\n\t" // bias it a bit toward weave - "pxor %%mm0, %%mm0\n\t" - "pcmpeqb %%mm0, %%mm7\n\t" // all ff where weave better, else 00 - "pcmpeqb %%mm7, %%mm0\n\t" // all ff where bob better, else 00 - "pand %%mm6, %%mm0\n\t" // use bob for these pixel values - "pand %%mm5, %%mm7\n\t" // use weave for these - "por %%mm7, %%mm0\n\t" // combine both -#endif - - - // pminub mm0, Max_Vals // but clip to catch the stray error - V_PMINUB ("%%mm0", _Max_Vals, "%%mm1") // but clip to catch the stray error - // pmaxub mm0, Min_Vals - V_PMAXUB ("%%mm0", _Min_Vals) - -#endif - - - MOVX" "_pDest", %%"XAX"\n\t" - -#ifdef USE_VERTICAL_FILTER - "movq %%mm0, %%mm1\n\t" - // pavgb mm0, qword ptr["XBX"] - V_PAVGB ("%%mm0", "(%%"XBX")", "%%mm2", _ShiftMask) - // movntq qword ptr["XAX"+"XDX"], mm0 - V_MOVNTQ ("(%"XAX", %%"XDX")", "%%mm0") - // pavgb mm1, qword ptr["XBX"+"XCX"] - V_PAVGB ("%%mm1", "(%%"XBX", %%"XCX")", "%%mm2", _ShiftMask) - //FIXME: XDX or XAX!! - "addq "_dst_pitchw", %%"XBX - // movntq qword ptr["XAX"+"XDX"], mm1 - V_MOVNTQ ("(%%"XAX", %%"XDX")", "%%mm1") -#else - - // movntq qword ptr["XAX"+"XDX"], mm0 - V_MOVNTQ ("(%%"XAX", %%"XDX")", "%%mm0") -#endif - - LEAX" 8(%%"XDX"), %%"XDX"\n\t" // bump offset pointer - CMPX" "_Last8", %%"XDX"\n\t" // done with line? - "jb 1b\n\t" // y - - MOVX" "_oldbx", %%"XBX"\n\t" - - : /* no outputs */ - - : "m"(pBob), - "m"(src_pitch2), - "m"(ShiftMask), - "m"(pDest), - "m"(dst_pitchw), - "m"(Last8), - "m"(pSrc), - "m"(pSrcP), - "m"(pBobP), - "m"(DiffThres), - "m"(Min_Vals), - "m"(Max_Vals), - "m"(FOURS), - "m"(TENS), - "m"(ONES), - "m"(UVMask), - "m"(Max_Mov), - "m"(YMask), - "m"(oldbx) - - : XAX, XCX, XDX, XSI, XDI, - "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", -#ifdef __MMX__ - "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", -#endif - "memory", "cc" - ); - - // adjust for next line - pSrc += src_pitch2; - pSrcP += src_pitch2; - pDest += dst_pitch2; - pBob += src_pitch2; - pBobP += src_pitch2; - } - - return 0; -#else -#ifdef SKIP_SEARCH - out[0] = best[0]; // just use the results of our wierd bob - out[1] = best[1]; -#else - diff[0] = diff[0] - MIN (diff[0], 10) - 4; - diff[1] = diff[1] - MIN (diff[1] - 10) - 4; - if (diff[0] < 0) - out[0] = weave[0]; - else - out[0] = best[0]; - - if (diff[1] < 0) - out[1] = weave[1]; - else - out[1] = best[1]; - - - out[0] = CLAMP (out[0], MinVals[0], MaxVals[0]); - out[1] = CLAMP (out[1], MinVals[1], MaxVals[1]); -#endif - -#ifdef USE_VERTICAL_FILTER - pDest[x] = (out[0] + pBob[0]) / 2; - pDest[x + dst_pitchw] = (pBob[src_pitch2] + out[0]) / 2; - pDest[x + 1] = (out[1] + pBob[1]) / 2; - pDest[x + 1 + dst_pitchw] = (pBob[src_pitch2 + 1] + out[1]) / 2; -#else - pDest[x] = out[0]; - pDest[x+1] = out[1]; -#endif - pBob += 2; - pBobP += 2; - pSrc += 2; - pSrcP += 2; - } - // adjust for next line - pSrc = src_pitch2 * (y+1) + pWeaveSrc; - pSrcP = src_pitch2 * (y+1) + pWeaveSrcP; - pDest = dst_pitch2 * (y+1) + pWeaveDest + dst_pitch2; - - - if (TopFirst) - { - pBob = pCopySrc + src_pitch2; - pBobP = pCopySrcP + src_pitch2; - } - else - { - pBob = pCopySrc; - pBobP = pCopySrcP; - } - - pBob += src_pitch2 * (y+1); - pBobP += src_pitch2 * (y+1); - } - - return 0; - -#endif diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA.inc deleted file mode 100644 index 6208fe8c..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA.inc +++ /dev/null @@ -1,11 +0,0 @@ -// -*- c++ -*- - -// Searches 2 pixel to the left and right, in both the old -// and new fields, but takes averages. These are even -// pixel addresses. Chroma match will be used. (YUY2) - MERGE4PIXavg("-4(%%"XDI")", "4(%%"XSI", %%"XCX", 2)") // up left, down right - MERGE4PIXavg("4(%%"XDI")", "-4(%%"XSI", %%"XCX", 2)") // up right, down left - MERGE4PIXavg("-4(%%"XDI", %%"XCX")", "4(%%"XSI", %%"XCX")") // left, right - MERGE4PIXavg("4(%%"XDI", %%"XCX")", "-4(%%"XSI", %%"XCX")") // right, left - MERGE4PIXavg("-4(%%"XDI", %%"XCX", 2)", "4(%%"XSI")") // down left, up right - MERGE4PIXavg("4(%%"XDI", %%"XCX", 2)", "-4(%%"XSI")") // down right, up left diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA8.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA8.inc deleted file mode 100644 index 2841c3f6..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopEdgeA8.inc +++ /dev/null @@ -1,12 +0,0 @@ -// -*- c++ -*- - -// Searches 4 pixel to the left and right, in both the old -// and new fields, but takes averages. These are even -// pixel addresses. Chroma match will be used. (YUY2) - MERGE4PIXavg("-8(%%"XDI")", "8(%%"XSI", %%"XCX", 2)") // up left, down right - MERGE4PIXavg("8(%%"XDI")", "-8(%%"XSI", %%"XCX", 2)") // up right, down left - MERGE4PIXavg("-8(%%"XDI", %%"XCX")", "8(%%"XSI", %%"XCX")") // left, right - MERGE4PIXavg("8(%%"XDI", %%"XCX")", "-8(%%"XSI", %%"XCX")") // right, left - MERGE4PIXavg("-8(%%"XDI", %%"XCX", 2)", "8(%%"XSI")") // down left, up right - MERGE4PIXavg("8(%%"XDI", %%"XCX", 2)", "-8(%%"XSI")") // down right, up left - diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA.inc deleted file mode 100644 index ab5375f4..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA.inc +++ /dev/null @@ -1,10 +0,0 @@ -// -*- c++ -*- - -// Searches 1 pixel to the left and right, in both the old -// and new fields, but takes averages. These are odd -// pixel addresses. Any chroma match will not be used. (YUY2) - MERGE4PIXavg("-2(%%"XDI")", "2(%%"XSI", %%"XCX", 2)") // up left, down right - MERGE4PIXavg("2(%%"XDI")", "-2(%%"XSI", %%"XCX", 2)") // up right, down left - MERGE4PIXavg("-2(%%"XDI", %%"XCX", 2)", "2(%%"XSI")") // down left, up right - MERGE4PIXavg("2(%%"XDI", %%"XCX", 2)", "-2(%%"XSI")") // down right, up left -#include "SearchLoopOddA2.inc" diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA2.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA2.inc deleted file mode 100644 index fd3f6fb0..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA2.inc +++ /dev/null @@ -1,5 +0,0 @@ -// Searches 1 pixel to the left and right, in both the old -// and new fields, but takes averages. These are odd -// pixel addresses. Any chroma match will not be used. (YUY2) - MERGE4PIXavg("-2(%%"XDI", %%"XCX")", "2(%%"XSI", %%"XCX")") // left, right - MERGE4PIXavg("2(%%"XDI", %%"XCX")", "-2(%%"XSI", %%"XCX")") // right, left diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA6.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA6.inc deleted file mode 100644 index cbae014e..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddA6.inc +++ /dev/null @@ -1,11 +0,0 @@ -// -*- c++ -*- - -// Searches 3 pixels to the left and right, in both the old -// and new fields, but takes averages. These are odd -// pixel addresses. Any chroma match will not be used. (YUY2) - MERGE4PIXavg("-6(%%"XDI")", "6(%%"XSI", %%"XCX", 2)") // up left, down right - MERGE4PIXavg("6(%%"XDI")", "-6(%%"XSI", %%"XCX", 2)") // up right, down left - MERGE4PIXavg("-6(%%"XDI", %%"XCX")", "6(%%"XSI", %%"XCX")") // left, right - MERGE4PIXavg("6(%%"XDI", %%"XCX")", "-6(%%"XSI", %%"XCX")") // right, left - MERGE4PIXavg("-6(%%"XDI", %%"XCX", 2)", "6(%%"XSI")") // down left, up right - MERGE4PIXavg("6(%%"XDI", %%"XCX", 2)", "-6(%%"XSI")") // down right, up left diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH.inc deleted file mode 100644 index e59e3c7e..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH.inc +++ /dev/null @@ -1,10 +0,0 @@ -// Searches 1 pixel to the left and right, in both the old -// and new fields, but takes v-half pel averages. These are odd -// pixel addresses. Any chroma match will not be used. (YUY2) - __asm - { - MERGE4PIXavgH("XDI"-2, "XDI"+"XCX"-2, "XSI"+"XCX"+2, "XSI"+2*"XCX"+2) // up left, down right - MERGE4PIXavgH("XDI"+2, "XDI"+"XCX"+2, "XSI"+"XCX"-2, "XSI"+2*"XCX"-2) // up right, down left - MERGE4PIXavgH("XDI"+2*"XCX"-2, "XDI"+"XCX"-2, "XSI"+"XCX"+2, "XSI"+2) // down left, up right - MERGE4PIXavgH("XDI"+2*"XCX"+2, "XDI"+"XCX"+2, "XSI"+"XCX"-2, "XSI"-2) // down right, up left - } diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH2.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH2.inc deleted file mode 100644 index cd7d812a..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopOddAH2.inc +++ /dev/null @@ -1,5 +0,0 @@ -// Searches 1 pixel to the left and right, in both the old -// and new fields, but takes vertical averages. These are odd -// pixel addresses. Any chroma match will not be used. (YUY2) - MERGE4PIXavgH("-2(%%"XDI", %%"XCX")", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "2(%%"XSI", %%"XCX")") // left, right - MERGE4PIXavgH("2(%%"XDI", %%"XCX")", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "-2(%%"XSI", %%"XCX")") // right, left diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopTop.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopTop.inc deleted file mode 100644 index 9d6a490f..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopTop.inc +++ /dev/null @@ -1,254 +0,0 @@ -// -*- c++ -*- - -unsigned char* pDest; -const unsigned char* pSrcP; -const unsigned char* pSrc; -const unsigned char* pBob; -const unsigned char* pBobP; - -// long is int32 on ARCH_368, int64 on ARCH_AMD64. Declaring it this way -// saves a lot of xor's to delete 64bit garbage. - -#if defined(DBL_RESIZE) || defined(USE_FOR_DSCALER) -long src_pitch2 = src_pitch; // even & odd lines are not interleaved in DScaler -#else -long src_pitch2 = 2 * src_pitch; // even & odd lines are interleaved in Avisynth -#endif - - -long dst_pitch2 = 2 * dst_pitch; -long y; - -long Last8; - - pSrc = pWeaveSrc; // points 1 weave line above - pSrcP = pWeaveSrcP; // " - -#ifdef DBL_RESIZE - -#ifdef USE_VERTICAL_FILTER - pDest = pWeaveDest + dst_pitch2; -#else - pDest = pWeaveDest + 3*dst_pitch; -#endif - -#else - -#ifdef USE_VERTICAL_FILTER - pDest = pWeaveDest + dst_pitch; -#else - pDest = pWeaveDest + dst_pitch2; -#endif - -#endif - - if (TopFirst) - { - pBob = pCopySrc + src_pitch2; // remember one weave line just copied previously - pBobP = pCopySrcP + src_pitch2; - } - else - { - pBob = pCopySrc; - pBobP = pCopySrcP; - } - -#ifndef IS_C - -#ifndef _pBob -#define _pBob "%0" -#define _src_pitch2 "%1" -#define _ShiftMask "%2" -#define _pDest "%3" -#define _dst_pitchw "%4" -#define _Last8 "%5" -#define _pSrc "%6" -#define _pSrcP "%7" -#define _pBobP "%8" -#define _DiffThres "%9" -#define _Min_Vals "%10" -#define _Max_Vals "%11" -#define _FOURS "%12" -#define _TENS "%13" -#define _ONES "%14" -#define _UVMask "%15" -#define _Max_Mov "%16" -#define _YMask "%17" -#define _oldbx "%18" -#endif - Last8 = (rowsize-8); - - for (y=1; y < FldHeight-1; y++) - { - long dst_pitchw = dst_pitch; // local stor so asm can ref - int64_t Max_Mov = 0x0404040404040404ull; - int64_t DiffThres = 0x0f0f0f0f0f0f0f0full; - int64_t YMask = 0x00ff00ff00ff00ffull; // keeps only luma - int64_t UVMask = 0xff00ff00ff00ff00ull; // keeps only chroma - int64_t TENS = 0x0a0a0a0a0a0a0a0aull; - int64_t FOURS = 0x0404040404040404ull; - int64_t ONES = 0x0101010101010101ull; - int64_t Min_Vals = 0x0000000000000000ull; - int64_t Max_Vals = 0x0000000000000000ull; - int64_t ShiftMask = 0xfefffefffefffeffull; - - long oldbx; - - // pretend it's indented -->> - __asm__ __volatile__ - ( - // Loop general reg usage - // - // XAX - pBobP, then pDest - // XBX - pBob - // XCX - src_pitch2 - // XDX - current offset - // XDI - prev weave pixels, 1 line up - // XSI - next weave pixels, 1 line up - - // Save "XBX" (-fPIC) - MOVX" %%"XBX", "_oldbx"\n\t" - - // simple bob first 8 bytes - MOVX" "_pBob", %%"XBX"\n\t" - MOVX" "_src_pitch2", %%"XCX"\n\t" - -#ifdef USE_VERTICAL_FILTER - "movq (%%"XBX"), %%mm0\n\t" - "movq (%%"XBX", %%"XCX"), %%mm1\n\t" //, qword ptr["XBX"+"XCX"] - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // halfway between - V_PAVGB ("%%mm0", "%%mm2", "%%mm3", _ShiftMask) // 1/4 way - V_PAVGB ("%%mm1", "%%mm2", "%%mm3", _ShiftMask) // 3/4 way - MOVX" "_pDest", %%"XDI"\n\t" - MOVX" "_dst_pitchw", %%"XAX"\n\t" - V_MOVNTQ ("(%%"XDI")", "%%mm0") - V_MOVNTQ ("(%%"XDI", %%"XAX")", "%%mm1") // qword ptr["XDI"+"XAX"], mm1 - - // simple bob last 8 bytes - MOVX" "_Last8", %%"XDX"\n\t" - LEAX" (%%"XBX", %%"XDX"), %%"XSI"\n\t" // ["XBX"+"XDX"] - "movq (%%"XSI"), %%mm0\n\t" - "movq (%%"XSI", %%"XCX"), %%mm1\n\t" // qword ptr["XSI"+"XCX"] - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // halfway between - V_PAVGB ("%%mm0", "%%mm2", "%%mm3", _ShiftMask) // 1/4 way - V_PAVGB ("%%mm1", "%%mm2", "%%mm3", _ShiftMask) // 3/4 way - ADDX" %%"XDX", %%"XDI"\n\t" // last 8 bytes of dest - V_MOVNTQ ("%%"XDI"", "%%mm0") - V_MOVNTQ ("(%%"XDI", %%"XAX")", "%%mm1") // qword ptr["XDI"+"XAX"], mm1) - -#else - "movq (%%"XBX"), %%mm0\n\t" - // pavgb mm0, qword ptr["XBX"+"XCX"] - V_PAVGB ("%%mm0", "(%%"XBX", %%"XCX")", "%%mm2", _ShiftMask) // qword ptr["XBX"+"XCX"], mm2, ShiftMask) - MOVX" "_pDest", %%"XDI"\n\t" - V_MOVNTQ ("(%%"XDI")", "%%mm0") - - // simple bob last 8 bytes - MOVX" "_Last8", %%"XDX"\n\t" - LEAX" (%%"XBX", %%"XDX"), %%"XSI"\n\t" //"XSI", ["XBX"+"XDX"] - "movq (%%"XSI"), %%mm0\n\t" - // pavgb mm0, qword ptr["XSI"+"XCX"] - V_PAVGB ("%%mm0", "(%%"XSI", %%"XCX")", "%%mm2", _ShiftMask) // qword ptr["XSI"+"XCX"], mm2, ShiftMask) - V_MOVNTQ ("(%%"XDI", %%"XDX")", "%%mm0") // qword ptr["XDI"+"XDX"], mm0) -#endif - // now loop and get the middle qwords - MOVX" "_pSrc", %%"XSI"\n\t" - MOVX" "_pSrcP", %%"XDI"\n\t" - MOVX" $8, %%"XDX"\n\t" // curr offset longo all lines - - "1:\n\t" - MOVX" "_pBobP", %%"XAX"\n\t" - ADDX" $8, %%"XDI"\n\t" - ADDX" $8, %%"XSI"\n\t" - ADDX" $8, %%"XBX"\n\t" - ADDX" %%"XDX", %%"XAX"\n\t" - -#ifdef USE_STRANGE_BOB -#include "StrangeBob.inc" -#else -#include "WierdBob.inc" -#endif - - // For non-SSE2: - // through out most of the rest of this loop we will maintain - // mm4 our min bob value - // mm5 best weave pixels so far - // mm6 our max Bob value - // mm7 best weighted pixel ratings so far - - // We will keep a slight bias to using the weave pixels - // from the current location, by rating them by the min distance - // from the Bob value instead of the avg distance from that value. - // our best and only rating so far - "pcmpeqb %%mm7, %%mm7\n\t" // ffff, say we didn't find anything good yet - -#else - Last8 = (rowsize - 4); - - for (y=1; y < FldHeight-1; y++) - { - #ifdef USE_STRANGE_BOB - long DiffThres = 0x0f; - #endif - - #ifndef SKIP_SEARCH - long weave[2], MaxVals[2], MinVals[2]; - #endif - - long diff[2], best[2], avg[2], diff2[2], out[2], x; - -#ifdef USE_VERTICAL_FILTER - pDest[0] = (3 * pBob[0] + pBob[src_pitch2]) / 4; - pDest[1] = (3 * pBob[1] + pBob[src_pitch2 + 1]) / 4; - pDest[2] = (3 * pBob[2] + pBob[src_pitch2 + 2]) / 4; - pDest[3] = (3 * pBob[3] + pBob[src_pitch2 + 3]) / 4; - pDest[dst_pitchw] = (pBob[0] + 3 * pBob[src_pitch2]) / 4; - pDest[dst_pitchw + 1] = (pBob[1] + 3 * pBob[src_pitch2 + 1]) / 4; - pDest[dst_pitchw + 2] = (pBob[2] + 3 * pBob[src_pitch2 + 2]) / 4; - pDest[dst_pitchw + 3] = (pBob[3] + 3 * pBob[src_pitch2 + 3]) / 4; - - // simple bob last byte - pDest[Last8] = (3 * pBob[Last8] + pBob[Last8 + src_pitch2]) / 4; - pDest[Last8 + 1] = (3 * pBob[Last8 + 1] + pBob[Last8 + src_pitch2 + 1]) / 4; - pDest[Last8 + 2] = (3 * pBob[Last8 + 2] + pBob[Last8 + src_pitch2 + 2]) / 4; - pDest[Last8 + 3] = (3 * pBob[Last8 + 3] + pBob[Last8 + src_pitch2 + 3]) / 4; - pDest[Last8 + src_pitch2] = (pBob[Last8] + 3 * pBob[Last8 + src_pitch2]) / 4; - pDest[Last8 + src_pitch2 + 1] = (pBob[Last8 + 1] + 3 * pBob[Last8 + src_pitch2 + 1]) / 4; - pDest[Last8 + src_pitch2 + 2] = (pBob[Last8 + 2] + 3 * pBob[Last8 + src_pitch2 + 2]) / 4; - pDest[Last8 + src_pitch2 + 3] = (pBob[Last8 + 3] + 3 * pBob[Last8 + src_pitch2 + 3]) / 4; -#else - pDest[0] = (pBob[0] + pBob[src_pitch2 + 1]) / 2; - pDest[1] = (pBob[1] + pBob[src_pitch2 + 1]) / 2; - pDest[2] = (pBob[2] + pBob[src_pitch2 + 2]) / 2; - pDest[3] = (pBob[3] + pBob[src_pitch2 + 3]) / 2; - - // simple bob last byte - pDest[Last8] = (pBob[Last8] + pBob[Last8 + src_pitch2]) / 2; - pDest[Last8 + 1] = (pBob[Last8 + 1] + pBob[Last8 + src_pitch2 + 1]) / 2; - pDest[Last8 + 2] = (pBob[Last8 + 2] + pBob[Last8 + src_pitch2 + 2]) / 2; - pDest[Last8 + 3] = (pBob[Last8 + 3] + pBob[Last8 + src_pitch2 + 3]) / 2; -#endif - - pBob += 4; - pBobP += 4; - pSrc += 4; - pSrcP += 4; - - for (x=4; x < Last8; x += 2) { - -#ifdef USE_STRANGE_BOB -#include "StrangeBob.inc" -#else -#include "WierdBob.inc" -#endif - - // We will keep a slight bias to using the weave pixels - // from the current location, by rating them by the min distance - // from the Bob value instead of the avg distance from that value. - // our best and only rating so far - diff[0] = diff[1] = 255; - - -#endif diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVA.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVA.inc deleted file mode 100644 index 3e3d19b5..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVA.inc +++ /dev/null @@ -1,6 +0,0 @@ -// -*- c++ -*- - -// Searches the center vertical line above center and below, in both the old -// and new fields, but takes averages. These are even pixel addresses. - MERGE4PIXavg("(%%"XDI", %%"XCX", 2)", "(%%"XSI")") // down, up - MERGE4PIXavg("(%%"XDI")", "(%%"XSI", %%"XCX", 2)") // up, down diff --git a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVAH.inc b/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVAH.inc deleted file mode 100644 index 33155bc1..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/SearchLoopVAH.inc +++ /dev/null @@ -1,6 +0,0 @@ -// -*- c++ -*- - -// Searches the center vertical line above center and below, in both the old -// and new fields, but takes averages. These are even pixel addresses. - MERGE4PIXavgH("(%%"XDI", %%"XCX", 2)", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "(%%"XSI")") // down, up - MERGE4PIXavgH("(%%"XDI")", "(%%"XDI", %%"XCX")", "(%%"XSI", %%"XCX")", "(%%"XSI", %%"XCX", 2)") // up, down diff --git a/gst/deinterlace2/tvtime/tomsmocomp/StrangeBob.inc b/gst/deinterlace2/tvtime/tomsmocomp/StrangeBob.inc deleted file mode 100644 index 45b4c865..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/StrangeBob.inc +++ /dev/null @@ -1,435 +0,0 @@ -// -*- c++ -*- - - // First, get and save our possible Bob values - // Assume our pixels are layed out as follows with x the calc'd bob value - // and the other pixels are from the current field - // - // j a b c k current field - // x calculated line - // m d e f n current field - // - // we calc the bob value luma value as: - // if |j - n| < Thres && |a - m| > Thres - // avg(j,n) - // end if - // if |k - m| < Thres && |c - n| > Thres - // avg(k,m) - // end if - // if |c - d| < Thres && |b - f| > Thres - // avg(c,d) - // end if - // if |a - f| < Thres && |b - d| > Thres - // avg(a,f) - // end if - // if |b - e| < Thres - // avg(b,e) - // end if - // pickup any thing not yet set with avg(b,e) - -#ifndef IS_C - - // j, n - "pxor %%mm5, %%mm5\n\t" - "pxor %%mm6, %%mm6\n\t" - "pxor %%mm7, %%mm7\n\t" - - "movq -2(%%"XBX"), %%mm0\n\t" // value a from top left - "movq -4(%%"XBX", %%"XCX"), %%mm1\n\t" // value m from bottom right - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(a,m) - - "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(a,m) > Thres else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(a,m) < Thres, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(a,m) > Thres, else 00 - - - "movq -4(%%"XBX"), %%mm0\n\t" // value j - "movq 4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(j,n) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm0\n\t" - "psubusb %%mm3, %%mm1\n\t" - "por %%mm1, %%mm0\n\t" // abs(j,n) - - "movq %%mm0, %%mm1\n\t" - "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(j,n) > Thres else 0 - "pxor %%mm3, %%mm3\n\t" - "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(j,n) < Thres, else 00 - - "pand %%mm4, %%mm1\n\t" - "pand %%mm1, %%mm2\n\t" - "pand %%mm1, %%mm0\n\t" - - "movq %%mm1, %%mm3\n\t" - "pxor %%mm5, %%mm3\n\t" - "pand %%mm3, %%mm6\n\t" - "pand %%mm3, %%mm7\n\t" - "pand %%mm3, %%mm5\n\t" - - "por %%mm1, %%mm5\n\t" - "por %%mm2, %%mm6\n\t" - "por %%mm0, %%mm7\n\t" - - // k & m - "movq 2(%%"XBX"), %%mm0\n\t" // value c from top left - "movq 4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n from bottom right - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(c,n) - - "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(c,n) > Thres else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(c,n) < Thres, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(c,n) > Thres, else 00 - - - "movq 4(%%"XBX"), %%mm0\n\t" // value k - "movq -4(%%"XBX", %%"XCX"), %%mm1\n\t" // value m - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(k,m) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm0\n\t" - "psubusb %%mm3, %%mm1\n\t" - "por %%mm1, %%mm0\n\t" // abs(k,m) - - "movq %%mm0, %%mm1\n\t" - "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(k,m) > Thres else 0 - "pxor %%mm3, %%mm3\n\t" - "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(k,m) < Thres, else 00 - - "pand %%mm4, %%mm1\n\t" - - "pand %%mm1, %%mm2\n\t" - "pand %%mm1, %%mm0\n\t" - - "movq %%mm1, %%mm3\n\t" - "pxor %%mm5, %%mm3\n\t" - "pand %%mm3, %%mm6\n\t" - "pand %%mm3, %%mm7\n\t" - "pand %%mm3, %%mm5\n\t" - - "por %%mm1, %%mm5\n\t" - "por %%mm2, %%mm6\n\t" - "por %%mm0, %%mm7\n\t" - - - // c & d - "movq (%%"XBX"), %%mm0\n\t" // value b from top left - "movq 2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f from bottom right - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(b,f) - - "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(b,f) > Thres else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(b,f) < Thres, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(b,f) > Thres, else 00 - - "movq 2(%%"XBX"), %%mm0\n\t" // value c - "movq -2(%%"XBX", %%"XCX"), %%mm1\n\t" // value d - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(c,d) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm0\n\t" - "psubusb %%mm3, %%mm1\n\t" - "por %%mm1, %%mm0\n\t" // abs(c,d) - - "movq %%mm0, %%mm1\n\t" - "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(c,d) > Thres else 0 - "pxor %%mm3, %%mm3\n\t" - "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(c,d) < Thres, else 00 - - "pand %%mm4, %%mm1\n\t" - - "pand %%mm1, %%mm2\n\t" - "pand %%mm1, %%mm0\n\t" - - "movq %%mm1, %%mm3\n\t" - "pxor %%mm5, %%mm3\n\t" - "pand %%mm3, %%mm6\n\t" - "pand %%mm3, %%mm7\n\t" - "pand %%mm3, %%mm5\n\t" - - "por %%mm1, %%mm5\n\t" - "por %%mm2, %%mm6\n\t" - "por %%mm0, %%mm7\n\t" - - // a & f - "movq (%%"XBX"), %%mm0\n\t" // value b from top left - "movq -2(%%"XBX", %%"XCX"), %%mm1\n\t" // value d from bottom right - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(b,d) - - "psubusb "_DiffThres", %%mm3\n\t" // nonzero where abs(b,d) > Thres else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where abs(b,d) < Thres, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where abs(b,d) > Thres, else 00 - - "movq -2(%%"XBX"), %%mm0\n\t" // value a - "movq 2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(a,f) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm0\n\t" - "psubusb %%mm3, %%mm1\n\t" - "por %%mm1, %%mm0\n\t" // abs(a,f) - - "movq %%mm0, %%mm1\n\t" - "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(a,f) > Thres else 0 - "pxor %%mm3, %%mm3\n\t" - "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(a,f) < Thres, else 00 - - "pand %%mm4, %%mm1\n\t" - - "pand %%mm1, %%mm2\n\t" - "pand %%mm1, %%mm0\n\t" - - "movq %%mm1, %%mm3\n\t" - "pxor %%mm5, %%mm3\n\t" - "pand %%mm3, %%mm6\n\t" - "pand %%mm3, %%mm7\n\t" - "pand %%mm3, %%mm5\n\t" - - "por %%mm1, %%mm5\n\t" - "por %%mm2, %%mm6\n\t" - "por %%mm0, %%mm7\n\t" - - "pand "_YMask", %%mm5\n\t" // mask out chroma from here - "pand "_YMask", %%mm6\n\t" // mask out chroma from here - "pand "_YMask", %%mm7\n\t" // mask out chroma from here - - // b,e - "movq (%%"XBX"), %%mm0\n\t" // value b from top - "movq (%%"XBX", %%"XCX"), %%mm1\n\t" // value e from bottom - "movq %%mm0, %%mm2\n\t" - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(b,e) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm0\n\t" - "psubusb %%mm3, %%mm1\n\t" - "por %%mm1, %%mm0\n\t" // abs(b,e) - - "movq %%mm0, %%mm1\n\t" - "psubusb "_DiffThres", %%mm1\n\t" // nonzero where abs(b,e) > Thres else 0 - "pxor %%mm3, %%mm3\n\t" - "pcmpeqb %%mm3, %%mm1\n\t" // now ff where abs(b,e) < Thres, else 00 - - "pand %%mm1, %%mm2\n\t" - "pand %%mm1, %%mm0\n\t" - - "movq %%mm1, %%mm3\n\t" - "pxor %%mm5, %%mm3\n\t" - "pand %%mm3, %%mm6\n\t" - "pand %%mm3, %%mm7\n\t" - "pand %%mm3, %%mm5\n\t" - - "por %%mm1, %%mm5\n\t" - "por %%mm2, %%mm6\n\t" - "por %%mm0, %%mm7\n\t" - - // bob in any leftovers - "movq (%%"XBX"), %%mm0\n\t" // value b from top - "movq (%%"XBX", %%"XCX"), %%mm1\n\t" // value e from bottom - - -// We will also calc here the max/min values to later limit comb -// so the max excursion will not exceed the Max_Comb constant - -#ifdef SKIP_SEARCH - "movq %%mm0, %%mm2\n\t" -// pminub %%mm2, %%mm1 - V_PMINUB ("%%mm2", "%%mm1", "%%mm4") - -// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this - V_PMAXUB ("%%mm6", "%%mm2") - "movq %%mm0, %%mm2\n\t" - V_PMAXUB ("%%mm2", "%%mm1") -// pminub %%mm6, %%mm2 // clip our current results so far to be below this - V_PMINUB ("%%mm6", "%%mm2", "%%mm4") - -#else - "movq %%mm0, %%mm2\n\t" - "movq (%%"XAX"), %%mm4\n\t" - "psubusb %%mm4, %%mm2\n\t" - "psubusb %%mm0, %%mm4\n\t" - "por %%mm2, %%mm4\n\t" // abs diff - - "movq %%mm1, %%mm2\n\t" - "movq (%%"XAX", %%"XCX"), %%mm3\n\t" - "psubusb %%mm3, %%mm2\n\t" - "psubusb %%mm1, %%mm3\n\t" - "por %%mm2, %%mm3\n\t" // abs diff -// pmaxub %%mm3, %%mm4 // top or bottom pixel moved most - V_PMAXUB ("%%mm3", "%%mm4") // top or bottom pixel moved most - "psubusb "_DiffThres", %%mm3\n\t" // moved more than allowed? or goes to 0? - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where low motion, else high motion - - "movq %%mm0, %%mm2\n\t" -// pminub %%mm2, %%mm1 - V_PMINUB ("%%mm2", "%%mm1", "%%mm4") - -// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this - V_PMAXUB ("%%mm6", "%%mm2") - - "psubusb %%mm3, %%mm2\n\t" // maybe decrease it to 0000.. if no surround motion - "movq %%mm2, "_Min_Vals"\n\t" - - "movq %%mm0, %%mm2\n\t" - V_PMAXUB ("%%mm2", "%%mm1") -// pminub %%mm6, %%mm2 // clip our current results so far to be below this - V_PMINUB ("%%mm6", "%%mm2", "%%mm4") - "paddusb %%mm3, %%mm2\n\t" // maybe increase it to ffffff if no surround motion - "movq %%mm2, "_Max_Vals"\n\t" -#endif - - "movq %%mm0, %%mm2\n\t" -// pavgb %%mm2, %%mm1 // avg(b,e) - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(b,e) - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(b,e) - "movq %%mm3, %%mm1\n\t" // keep copy of diffs - - "pxor %%mm4, %%mm4\n\t" - "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 - "pcmpeqb %%mm0, %%mm0\n\t" - "pandn %%mm0, %%mm5\n\t" - "por %%mm5, %%mm3\n\t" - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 - - "pand %%mm3, %%mm1\n\t" - "pand %%mm3, %%mm2\n\t" - - "pand %%mm4, %%mm6\n\t" - "pand %%mm4, %%mm7\n\t" - - "por %%mm2, %%mm6\n\t" // our x2 value - "por %%mm1, %%mm7\n\t" // our x2 diffs - "movq %%mm7, %%mm4\n\t" // save as bob uncertainty indicator - -#else - - diff[0] = -1; - diff[1] = -1; - best[0] = 0; - best[1] = 0; - // j, n - if (ABS (pBob[-2] - pBob[src_pitch2 - 4]) < DiffThres && - ABS (pBob[-4] - pBob[src_pitch2 + 4]) > DiffThres) { - best[0] = (pBob[-2] + pBob[src_pitch2 - 4]) / 2; - diff[0] = ABS (pBob[-2] - pBob[src_pitch2 - 4]); - } - if (ABS (pBob[-1] - pBob[src_pitch2 - 3]) < DiffThres && - ABS (pBob[-3] - pBob[src_pitch2 + 5]) > DiffThres) { - best[1] = (pBob[-1] + pBob[src_pitch2 - 3]) / 2; - diff[1] = ABS (pBob[-1] - pBob[src_pitch2 - 3]); - } - - // k & m - if (ABS (pBob[2] - pBob[src_pitch2 + 4]) < DiffThres && - ABS (pBob[4] - pBob[src_pitch2 - 4]) > DiffThres) { - best[0] = (pBob[4] + pBob[src_pitch2 - 4]) / 2; - diff[0] = ABS (pBob[4] - pBob[src_pitch2 - 4]); - } - - if (ABS (pBob[3] - pBob[src_pitch2 + 5]) < DiffThres && - ABS (pBob[5] - pBob[src_pitch2 - 3]) > DiffThres) { - best[1] = (pBob[5] + pBob[src_pitch2 - 3]) / 2; - diff[1] = ABS (pBob[5] - pBob[src_pitch2 - 3]); - } - - // c & d - if (ABS (pBob[0] - pBob[src_pitch2 + 2]) < DiffThres && - ABS (pBob[2] - pBob[src_pitch2 - 2]) > DiffThres) { - best[0] = (pBob[2] + pBob[src_pitch2 - 2]) / 2; - diff[0] = ABS (pBob[2] - pBob[src_pitch2 - 2]); - } - - if (ABS (pBob[1] - pBob[src_pitch2 + 3]) < DiffThres && - ABS (pBob[3] - pBob[src_pitch2 - 1]) > DiffThres) { - best[1] = (pBob[3] + pBob[src_pitch2 - 1]) / 2; - diff[1] = ABS (pBob[3] - pBob[src_pitch2 - 1]); - } - - // a & f - if (ABS (pBob[0] - pBob[src_pitch2 - 2]) < DiffThres && - ABS (pBob[-2] - pBob[src_pitch2 + 2]) > DiffThres) { - best[0] = (pBob[-2] + pBob[src_pitch2 + 2]) / 2; - diff[0] = ABS (pBob[-2] - pBob[src_pitch2 + 2]); - } - - if (ABS (pBob[1] - pBob[src_pitch2 - 1]) < DiffThres && - ABS (pBob[-1] - pBob[src_pitch2 + 3]) > DiffThres) { - best[1] = (pBob[-1] + pBob[src_pitch2 + 3]) / 2; - diff[1] = ABS (pBob[-1] - pBob[src_pitch2 + 3]); - } - - // b,e - if (ABS (pBob[0] - pBob[src_pitch2]) < DiffThres) { - best[0] = (pBob[0] + pBob[src_pitch2]) / 2; - diff[0] = ABS (pBob[0] - pBob[src_pitch2]); - } - - if (ABS (pBob[1] - pBob[src_pitch2 + 1]) < DiffThres) { - best[1] = (pBob[1] + pBob[src_pitch2 + 1]) / 2; - diff[1] = ABS (pBob[1] - pBob[src_pitch2 + 1]); - } - - -// We will also calc here the max/min values to later limit comb -// so the max excursion will not exceed the Max_Comb constant - -#ifdef SKIP_SEARCH - best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); - best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); -#else - mov[0] = MAX (ABS (pBob[0] - pBobP[0]), ABS (pBob[src_pitch2] - pBobP[src_pitch2])); - mov[1] = MAX (ABS (pBob[1] - pBobP[1]), ABS (pBob[src_pitch2 + 1] - pBobP[src_pitch2 + 1])); - - MinVals[0] = 0; - MinVals[1] = 0; - MaxVals[0] = 255; - MaxVals[1] = 255; - if (mov[0] > DiffThres) { - MinVals[0] = MAX (MIN (pBob[0], pBob[src_pitch2]), best[0]); - MaxVals[0] = MIN (MAX (pBob[0], pBob[src_pitch2]), best[0]); - } - - if (mov[1] > DiffThres) { - MinVals[1] = MAX (MIN (pBob[1], pBob[src_pitch2+1]), best[1]); - MaxVals[1] = MIN (MAX (pBob[1], pBob[src_pitch2+1]), best[1]); - } - - best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); - best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); -#endif - avg[0] = (pBob[src_pitch2] + pBob[0]) / 2; - avg[1] = (pBob[src_pitch2 + 1] + pBob[1]) / 2; - diff2[0] = ABS (pBob[src_pitch2 + 1] - pBob[1]); - diff2[1] = ABS (pBob[src_pitch2 + 1] - pBob[1]); - - if (diff[0] == -1 || diff2[0] < diff[0]) { - best[0] = avg[0]; - diff[0] = diff2[0]; - } - - if (diff[1] == -1 || diff2[1] < diff[1]) { - best[1] = avg[1]; - diff[1] = diff2[1]; - } -#endif diff --git a/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc b/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc deleted file mode 100644 index 89ed39e4..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc +++ /dev/null @@ -1,241 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2002 Tom Barry All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Relicensed for GStreamer from GPL to LGPL with permit from Tom Barry. - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - - -#ifndef TopFirst -#define TopFirst IsOdd -#endif - -#ifdef SEFUNC -#undef SEFUNC -#endif - -#if defined(IS_MMXEXT) -#define SEFUNC(x) Search_Effort_MMXEXT_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) -#elif defined(IS_3DNOW) -#define SEFUNC(x) Search_Effort_3DNOW_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) -#elif defined(IS_MMX) -#define SEFUNC(x) Search_Effort_MMX_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) -#else -#define SEFUNC(x) Search_Effort_C_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight) -#endif - -#include "TomsMoCompAll2.inc" - -#define USE_STRANGE_BOB - -#include "TomsMoCompAll2.inc" - -#undef USE_STRANGE_BOB - -#undef SEFUNC -#if defined(IS_MMXEXT) -#define SEFUNC(x) Search_Effort_MMXEXT_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) -#elif defined(IS_3DNOW) -#define SEFUNC(x) Search_Effort_3DNOW_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) -#elif defined(IS_MMX) -#define SEFUNC(x) Search_Effort_MMX_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) -#else -#define SEFUNC(x) Search_Effort_C_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight) -#endif - -void FUNCT_NAME(GstDeinterlaceMethod *d_method, GstDeinterlace2* object, GstBuffer *outbuf) -{ - GstDeinterlaceMethodTomsMoComp *self = GST_DEINTERLACE_METHOD_TOMSMOCOMP (d_method); - long SearchEffort = self->search_effort; - int UseStrangeBob = self->strange_bob; - int IsOdd; - const unsigned char *pWeaveSrc; - const unsigned char *pWeaveSrcP; - unsigned char *pWeaveDest; - const unsigned char *pCopySrc; - const unsigned char *pCopySrcP; - unsigned char *pCopyDest; - int src_pitch; - int dst_pitch; - int rowsize; - int FldHeight; - - /* double stride do address just every odd/even scanline */ - src_pitch = object->field_stride; - dst_pitch = object->row_stride; - rowsize = object->row_stride; - FldHeight = object->field_height; - - pCopySrc = GST_BUFFER_DATA(object->field_history[object->history_count-1].buf); - pCopySrcP = GST_BUFFER_DATA(object->field_history[object->history_count-3].buf); - pWeaveSrc = GST_BUFFER_DATA(object->field_history[object->history_count-2].buf); - pWeaveSrcP = GST_BUFFER_DATA(object->field_history[object->history_count-4].buf); - - /* use bottom field and interlace top field */ - if (object->field_history[object->history_count-2].flags == PICTURE_INTERLACED_BOTTOM) { - IsOdd = 1; - - // if we have an odd field we copy an even field and weave an odd field - pCopyDest = GST_BUFFER_DATA(outbuf); - pWeaveDest = pCopyDest + dst_pitch; - } - /* do it vice verca */ - else { - - IsOdd = 0; - // if we have an even field we copy an odd field and weave an even field - pCopyDest = GST_BUFFER_DATA(outbuf) + dst_pitch; - pWeaveDest = GST_BUFFER_DATA(outbuf); - } - - - // copy 1st and last weave lines - Fieldcopy(pWeaveDest, pCopySrc, rowsize, - 1, dst_pitch*2, src_pitch); - Fieldcopy(pWeaveDest+(FldHeight-1)*dst_pitch*2, - pCopySrc+(FldHeight-1)*src_pitch, rowsize, - 1, dst_pitch*2, src_pitch); - -#ifdef USE_VERTICAL_FILTER - // Vertical Filter currently not implemented for DScaler !! - // copy 1st and last lines the copy field - Fieldcopy(pCopyDest, pCopySrc, rowsize, - 1, dst_pitch*2, src_pitch); - Fieldcopy(pCopyDest+(FldHeight-1)*dst_pitch*2, - pCopySrc+(FldHeight-1)*src_pitch, rowsize, - 1, dst_pitch*2, src_pitch); -#else - - // copy all of the copy field - Fieldcopy(pCopyDest, pCopySrc, rowsize, - FldHeight, dst_pitch*2, src_pitch); -#endif - // then go fill in the hard part, being variously lazy depending upon - // SearchEffort - - if(!UseStrangeBob) { - if (SearchEffort == 0) - { - SEFUNC(0); - } - else if (SearchEffort <= 1) - { - SEFUNC(1); - } - /* else if (SearchEffort <= 2) - { - SEFUNC(2); - } - */ - else if (SearchEffort <= 3) - { - SEFUNC(3); - } - else if (SearchEffort <= 5) - { - SEFUNC(5); - } - else if (SearchEffort <= 9) - { - SEFUNC(9); - } - else if (SearchEffort <= 11) - { - SEFUNC(11); - } - else if (SearchEffort <= 13) - { - SEFUNC(13); - } - else if (SearchEffort <= 15) - { - SEFUNC(15); - } - else if (SearchEffort <= 19) - { - SEFUNC(19); - } - else if (SearchEffort <= 21) - { - SEFUNC(21); - } - else - { - SEFUNC(Max); - } - } - else - { - if (SearchEffort == 0) - { - SEFUNC(0SB); - } - else if (SearchEffort <= 1) - { - SEFUNC(1SB); - } - /* else if (SearchEffort <= 2) - { - SEFUNC(2SB); - } - */ - else if (SearchEffort <= 3) - { - SEFUNC(3SB); - } - else if (SearchEffort <= 5) - { - SEFUNC(5SB); - } - else if (SearchEffort <= 9) - { - SEFUNC(9SB); - } - else if (SearchEffort <= 11) - { - SEFUNC(11SB); - } - else if (SearchEffort <= 13) - { - SEFUNC(13SB); - } - else if (SearchEffort <= 15) - { - SEFUNC(15SB); - } - else if (SearchEffort <= 19) - { - SEFUNC(19SB); - } - else if (SearchEffort <= 21) - { - SEFUNC(21SB); - } - else - { - SEFUNC(MaxSB); - } - } - -#if defined(BUILD_X86_ASM) && !defined(IS_C) - __asm__ __volatile__("emms"); -#endif -} diff --git a/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll2.inc b/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll2.inc deleted file mode 100644 index f6344eab..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll2.inc +++ /dev/null @@ -1,243 +0,0 @@ -// -*- c++ -*- - -#ifdef SEARCH_EFFORT_FUNC -#undef SEARCH_EFFORT_FUNC -#endif - -#ifdef USE_STRANGE_BOB -#define SEARCH_EFFORT_FUNC(n) SEFUNC(n##SB) -#else -#define SEARCH_EFFORT_FUNC(n) SEFUNC(n) -#endif - -static inline int SEARCH_EFFORT_FUNC(0) // we don't try at all ;-) -{ - //see Search_Effort_Max() for comments -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -} - -static inline int SEARCH_EFFORT_FUNC(1) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see Search_Effort_Max() for comments -#include "SearchLoopTop.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -static inline int SEARCH_EFFORT_FUNC(3) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see Search_Effort_Max() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA2.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -static inline int SEARCH_EFFORT_FUNC(5) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see Search_Effort_Max() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA2.inc" -#include "SearchLoopOddAH2.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// 3x3 search -static inline int SEARCH_EFFORT_FUNC(9) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchEffortMax() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoopVA.inc" -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// Search 9 with 2 H-half pels added -static inline int SEARCH_EFFORT_FUNC(11) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchEffortMax() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA.inc" -#include "SearchLoopOddAH2.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoopVA.inc" -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// Search 11 with 2 V-half pels added -static inline int SEARCH_EFFORT_FUNC(13) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchEffortMax() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA.inc" -#include "SearchLoopOddAH2.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoopVAH.inc" -#include "SearchLoopVA.inc" -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// 5x3 -static inline int SEARCH_EFFORT_FUNC(15) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchEffortMax() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoopEdgeA.inc" -#include "SearchLoopVA.inc" -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// 5x3 + 4 half pels -static inline int SEARCH_EFFORT_FUNC(19) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchEffortMax() for comments -#include "SearchLoopTop.inc" -#include "SearchLoopOddA.inc" -#include "SearchLoopOddAH2.inc" - RESET_CHROMA // pretend chroma diffs was 255 each -#include "SearchLoopEdgeA.inc" -#include "SearchLoopVAH.inc" -#include "SearchLoopVA.inc" -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// Handle one 4x1 block of pixels -// Search a 7x3 area, no half pels - -static inline int SEARCH_EFFORT_FUNC(21) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchLoopTop.inc for comments -#include "SearchLoopTop.inc" - - // odd addresses -- the pixels at odd address wouldn't generate - // good luma values but we will mask those off - -#include "SearchLoopOddA6.inc" // 4 odd v half pels, 3 to left & right -#include "SearchLoopOddA.inc" // 6 odd pels, 1 to left & right - - RESET_CHROMA // pretend chroma diffs was 255 each - - // even addresses -- use both luma and chroma from these - // search averages of 2 pixels left and right -#include "SearchLoopEdgeA.inc" - // search vertical line and averages, -1,0,+1 -#include "SearchLoopVA.inc" - // blend our results and loop -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -// Handle one 4x1 block of pixels -// Search a 9x3 area, no half pels -static inline int SEARCH_EFFORT_FUNC(Max) -{ -#ifdef IS_C -#define SKIP_SEARCH -#include "SearchLoopTop.inc" -#include "SearchLoopBottom.inc" -#undef SKIP_SEARCH -#else - //see SearchLoopTop.inc for comments -#include "SearchLoopTop.inc" - - // odd addresses -- the pixels at odd address wouldn't generate - // good luma values but we will mask those off - -#include "SearchLoopOddA6.inc" // 4 odd v half pels, 3 to left & right -#include "SearchLoopOddA.inc" // 6 odd pels, 1 to left & right - - RESET_CHROMA // pretend chroma diffs was 255 each - - // even addresses -- use both luma and chroma from these - // search averages of 4 pixels left and right -#include "SearchLoopEdgeA8.inc" - // search averages of 2 pixels left and right -#include "SearchLoopEdgeA.inc" - // search vertical line and averages, -1,0,+1 -#include "SearchLoopVA.inc" - // blend our results and loop -#include "SearchLoop0A.inc" -#include "SearchLoopBottom.inc" -#endif -} - -#undef SEARCH_EFFORT_FUNC - diff --git a/gst/deinterlace2/tvtime/tomsmocomp/WierdBob.inc b/gst/deinterlace2/tvtime/tomsmocomp/WierdBob.inc deleted file mode 100644 index f4bbb830..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/WierdBob.inc +++ /dev/null @@ -1,286 +0,0 @@ -// -*- c++ -*- - - // First, get and save our possible Bob values - // Assume our pixels are layed out as follows with x the calc'd bob value - // and the other pixels are from the current field - // - // j a b c k current field - // x calculated line - // m d e f n current field - // - // we calc the bob value as: - // x2 = either avg(a,f), avg(c,d), avg(b,e), avg(j,n), or avg(k,m) - - // selected for the smallest of abs(a,f), abs(c,d), or abs(b,e), etc. - -#ifndef IS_C - // a,f - "movq -2(%%"XBX"), %%mm0\n\t" // value a from top left - "movq 2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f from bottom right - "movq %%mm0, %%mm6\n\t" -// pavgb %%mm6, %%mm1 // avg(a,f), also best so far - V_PAVGB ("%%mm6", "%%mm1", "%%mm7", _ShiftMask) // avg(a,f), also best so far - "movq %%mm0, %%mm7\n\t" - "psubusb %%mm1, %%mm7\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm7\n\t" // abs diff, also best so far - - // c,d - "movq 2(%%"XBX"), %%mm0\n\t" // value a from top left - "movq -2(%%"XBX", %%"XCX"), %%mm1\n\t" // value f from bottom right - "movq %%mm0, %%mm2\n\t" -// pavgb %%mm2, %%mm1 // avg(c,d) - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(c,d) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(c,d) - "movq %%mm3, %%mm1\n\t" // keep copy - - "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 - - "pand %%mm3, %%mm1\n\t" // keep only better new avg and abs - "pand %%mm3, %%mm2\n\t" - - "pand %%mm4, %%mm6\n\t" - "pand %%mm4, %%mm7\n\t" - - "por %%mm2, %%mm6\n\t" // and merge new & old vals keeping best - "por %%mm1, %%mm7\n\t" - "por "_UVMask", %%mm7\n\t" // but we know chroma is worthless so far - "pand "_YMask", %%mm5\n\t" // mask out chroma from here also - - // j,n - "movq -4(%%"XBX"), %%mm0\n\t" // value j from top left - "movq 4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n from bottom right - "movq %%mm0, %%mm2\n\t" -// pavgb %%mm2, %%mm1 // avg(j,n) - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(j,n) - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(j-n) - "movq %%mm3, %%mm1\n\t" // keep copy - - "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 - - "pand %%mm3, %%mm1\n\t" // keep only better new avg and abs - "pand %%mm2, %%mm3\n\t" - - "pand %%mm4, %%mm6\n\t" - "pand %%mm4, %%mm7\n\t" - - "por %%mm3, %%mm6\n\t" // and merge new & old vals keeping best - "por %%mm1, %%mm7\n\t" // " - - // k, m - "movq 4(%%"XBX"), %%mm0\n\t" // value k from top right - "movq -4(%%"XBX", %%"XCX"), %%mm1\n\t" // value n from bottom left - "movq %%mm0, %%mm4\n\t" -// pavgb %%mm4, %%mm1 // avg(k,m) - V_PAVGB ("%%mm4", "%%mm1", "%%mm3", _ShiftMask) // avg(k,m) - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(k,m) - "movq %%mm3, %%mm1\n\t" // keep copy - - "movq %%mm4, %%mm2\n\t" // avg(k,m) - - "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 - - "pand %%mm3, %%mm1\n\t" // keep only better new avg and abs - "pand %%mm2, %%mm3\n\t" - - "pand %%mm4, %%mm6\n\t" - "pand %%mm4, %%mm7\n\t" - - "por %%mm3, %%mm6\n\t" // and merge new & old vals keeping best - "por %%mm1, %%mm7\n\t" // " - - // b,e - "movq (%%"XBX"), %%mm0\n\t" // value b from top - "movq (%%"XBX", %%"XCX"), %%mm1\n\t" // value e from bottom - -// We will also calc here the max/min values to later limit comb -// so the max excursion will not exceed the Max_Comb constant - -#ifdef SKIP_SEARCH - "movq %%mm0, %%mm2\n\t" -// pminub %%mm2, %%mm1 - V_PMINUB ("%%mm2", "%%mm1", "%%mm4") - -// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this - V_PMAXUB ("%%mm6", "%%mm2") - "movq %%mm0, %%mm2\n\t" - V_PMAXUB ("%%mm2", "%%mm1") -// pminub %%mm6, %%mm2 // clip our current results so far to be below this - V_PMINUB ("%%mm6", "%%mm2", "%%mm4") - -#else - "movq %%mm0, %%mm2\n\t" - "movq (%%"XAX"), %%mm4\n\t" - "psubusb %%mm4, %%mm2\n\t" - "psubusb %%mm0, %%mm4\n\t" - "por %%mm2, %%mm4\n\t" // abs diff - - "movq %%mm1, %%mm2\n\t" - "movq (%%"XAX", %%"XCX"), %%mm3\n\t" - "psubusb %%mm3, %%mm2\n\t" - "psubusb %%mm1, %%mm3\n\t" - "por %%mm2, %%mm3\n\t" // abs diff -// pmaxub %%mm3, %%mm4 // top or bottom pixel moved most - V_PMAXUB ("%%mm3", "%%mm4") // top or bottom pixel moved most - "psubusb "_Max_Mov", %%mm3\n\t" // moved more than allowed? or goes to 0? - "pxor %%mm4, %%mm4\n\t" - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where low motion, else high motion - - "movq %%mm0, %%mm2\n\t" -// pminub %%mm2, %%mm1 - V_PMINUB ("%%mm2", "%%mm1", "%%mm4") - -// pmaxub %%mm6, %%mm2 // clip our current results so far to be above this - V_PMAXUB ("%%mm6", "%%mm2") - - "psubusb %%mm3, %%mm2\n\t" // maybe decrease it to 0000.. if no surround motion - "movq %%mm2, "_Min_Vals"\n\t" - - "movq %%mm0, %%mm2\n\t" - V_PMAXUB ("%%mm2", "%%mm1") -// pminub %%mm6, %%mm2 // clip our current results so far to be below this - V_PMINUB ("%%mm6", "%%mm2", "%%mm4") - "paddusb %%mm3, %%mm2\n\t" // maybe increase it to ffffff if no surround motion - "movq %%mm2, "_Max_Vals"\n\t" -#endif - - "movq %%mm0, %%mm2\n\t" -// pavgb %%mm2, %%mm1 // avg(b,e) - V_PAVGB ("%%mm2", "%%mm1", "%%mm3", _ShiftMask) // avg(b,e) - - "movq %%mm0, %%mm3\n\t" - "psubusb %%mm1, %%mm3\n\t" - "psubusb %%mm0, %%mm1\n\t" - "por %%mm1, %%mm3\n\t" // abs(c,d) - "movq %%mm3, %%mm1\n\t" // keep copy of diffs - - "pxor %%mm4, %%mm4\n\t" - "psubusb %%mm7, %%mm3\n\t" // nonzero where new weights bigger, else 0 - "pcmpeqb %%mm4, %%mm3\n\t" // now ff where new better, else 00 - - "pcmpeqb %%mm3, %%mm4\n\t" // here ff where old better, else 00 - - "pand %%mm3, %%mm1\n\t" - "pand %%mm3, %%mm2\n\t" - - "pand %%mm4, %%mm6\n\t" - "pand %%mm4, %%mm7\n\t" - - "por %%mm2, %%mm6\n\t" // our x2 value - "por %%mm1, %%mm7\n\t" // our x2 diffs - "movq %%mm7, %%mm4\n\t" // save as bob uncertainty indicator - -#else - - // a,f - best[0] = (pBob[-2] + pBob[src_pitch2 + 2]) / 2; - diff[0] = ABS (pBob[-2] - pBob[src_pitch2 + 2]); - best[1] = (pBob[-1] + pBob[src_pitch2 + 3]) / 2; - diff[1] = ABS (pBob[-1] - pBob[src_pitch2 + 3]); - - // c,d - if (ABS (pBob[2] - pBob[src_pitch2 - 2]) < diff[0]) { - best[0] = (pBob[2] + pBob[src_pitch2 - 2]) / 2; - diff[0] = ABS (pBob[2] - pBob[src_pitch2 - 2]); - } - - if (ABS (pBob[3] - pBob[src_pitch2 - 1]) < diff[1]) { - best[1] = (pBob[3] + pBob[src_pitch2 - 1]) / 2; - diff[1] = ABS (pBob[3] - pBob[src_pitch2 - 1]); - } - - // j,n - if (ABS (pBob[-4] - pBob[src_pitch2 + 4]) < diff[0]) { - best[0] = (pBob[-4] + pBob[src_pitch2 + 4]) / 2; - diff[0] = ABS (pBob[-4] - pBob[src_pitch2 + 4]); - } - - if (ABS (pBob[-3] - pBob[src_pitch2 + 5]) < diff[1]) { - best[1] = (pBob[-3] + pBob[src_pitch2 + 5]) / 2; - diff[1] = ABS (pBob[-3] - pBob[src_pitch2 + 5]); - } - - // k,m - if (ABS (pBob[4] - pBob[src_pitch2 - 4]) < diff[0]) { - best[0] = (pBob[4] + pBob[src_pitch2 - 4]) / 2; - diff[0] = ABS (pBob[-4] - pBob[src_pitch2 - 4]); - } - - if (ABS (pBob[5] - pBob[src_pitch2 - 3]) < diff[1]) { - best[1] = (pBob[5] + pBob[src_pitch2 - 3]) / 2; - diff[1] = ABS (pBob[-3] - pBob[src_pitch2 - 3]); - } - // k,m - if (ABS (pBob[4] - pBob[src_pitch2 - 4]) < diff[0]) { - best[0] = (pBob[4] + pBob[src_pitch2 - 4]) / 2; - diff[0] = ABS (pBob[-4] - pBob[src_pitch2 - 4]); - } - - if (ABS (pBob[5] - pBob[src_pitch2 - 3]) < diff[1]) { - best[1] = (pBob[5] + pBob[src_pitch2 - 3]) / 2; - diff[1] = ABS (pBob[-3] - pBob[src_pitch2 - 3]); - } - -// We will also calc here the max/min values to later limit comb -// so the max excursion will not exceed the Max_Comb constant - -#ifdef SKIP_SEARCH - best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); - best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); -#else - mov[0] = MAX (ABS (pBob[0] - pBobP[0]), ABS (pBob[src_pitch2] - pBobP[src_pitch2])); - mov[1] = MAX (ABS (pBob[1] - pBobP[1]), ABS (pBob[src_pitch2 + 1] - pBobP[src_pitch2 + 1])); - - MinVals[0] = 0; - MinVals[1] = 0; - MaxVals[0] = 255; - MaxVals[1] = 255; - - if (mov[0] > Max_Mov[0]) { - MinVals[0] = MAX (MIN (pBob[0], pBob[src_pitch2]), best[0]); - MaxVals[0] = MIN (MAX (pBob[0], pBob[src_pitch2]), best[0]); - } - - if (mov[1] > Max_Mov[1]) { - MinVals[1] = MAX (MIN (pBob[1], pBob[src_pitch2 + 1]), best[1]); - MaxVals[1] = MIN (MAX (pBob[1], pBob[src_pitch2 + 1]), best[1]); - } - - best[0] = CLAMP (best[0], MIN (pBob[src_pitch2], pBob[0]), MAX (pBob[src_pitch2], pBob[0])); - best[1] = CLAMP (best[1], MIN (pBob[src_pitch2 + 1], pBob[1]), MAX (pBob[src_pitch2 + 1], pBob[1])); -#endif - - avg[0] = (pBob[src_pitch2] + pBob[0]) / 2; - avg[1] = (pBob[src_pitch2 + 1] + pBob[1]) / 2; - diff2[0] = ABS (pBob[src_pitch2] - pBob[0]); - diff2[1] = ABS (pBob[src_pitch2 + 1] - pBob[1]); - - if (diff2[0] < diff[0]) { - best[0] = avg[0]; - diff[0] = diff2[0]; - } - - if (diff2[1] < diff[1]) { - best[1] = avg[1]; - diff[1] = diff2[1]; - } -#endif diff --git a/gst/deinterlace2/tvtime/tomsmocomp/tomsmocompmacros.h b/gst/deinterlace2/tvtime/tomsmocomp/tomsmocompmacros.h deleted file mode 100644 index 7e8147ec..00000000 --- a/gst/deinterlace2/tvtime/tomsmocomp/tomsmocompmacros.h +++ /dev/null @@ -1,164 +0,0 @@ -#include -#include - -// Define a few macros for CPU dependent instructions. -// I suspect I don't really understand how the C macro preprocessor works but -// this seems to get the job done. // TRB 7/01 - -// BEFORE USING THESE YOU MUST SET: - -// #define SIMD_TYPE MMXEXT (or MMX or 3DNOW) - -// some macros for pavgb instruction -// V_PAVGB(mmr1, mmr2, mmr work register, smask) mmr2 may = mmrw if you can trash it - -#define V_PAVGB_MMX(mmr1, mmr2, mmrw, smask) \ - "movq "mmr2", "mmrw"\n\t" \ - "pand "smask", "mmrw"\n\t" \ - "psrlw $1, "mmrw"\n\t" \ - "pand "smask", "mmr1"\n\t" \ - "psrlw $1, "mmr1"\n\t" \ - "paddusb "mmrw", "mmr1"\n\t" -#define V_PAVGB_MMXEXT(mmr1, mmr2, mmrw, smask) "pavgb "mmr2", "mmr1"\n\t" -#define V_PAVGB_3DNOW(mmr1, mmr2, mmrw, smask) "pavgusb "mmr2", "mmr1"\n\t" -#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SIMD_TYPE) -#define V_PAVGB2(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) -#define V_PAVGB3(mmr1, mmr2, mmrw, smask, simd_type) V_PAVGB_##simd_type(mmr1, mmr2, mmrw, smask) - -// some macros for pmaxub instruction -#define V_PMAXUB_MMX(mmr1, mmr2) \ - "psubusb "mmr2", "mmr1"\n\t" \ - "paddusb "mmr2", "mmr1"\n\t" -#define V_PMAXUB_MMXEXT(mmr1, mmr2) "pmaxub "mmr2", "mmr1"\n\t" -#define V_PMAXUB_3DNOW(mmr1, mmr2) V_PMAXUB_MMX(mmr1, mmr2) // use MMX version -#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SIMD_TYPE) -#define V_PMAXUB2(mmr1, mmr2, simd_type) V_PMAXUB3(mmr1, mmr2, simd_type) -#define V_PMAXUB3(mmr1, mmr2, simd_type) V_PMAXUB_##simd_type(mmr1, mmr2) - -// some macros for pminub instruction -// V_PMINUB(mmr1, mmr2, mmr work register) mmr2 may NOT = mmrw -#define V_PMINUB_MMX(mmr1, mmr2, mmrw) \ - "pcmpeqb "mmrw", "mmrw"\n\t" \ - "psubusb "mmr2", "mmrw"\n\t" \ - "paddusb "mmrw", "mmr1"\n\t" \ - "psubusb "mmrw", "mmr1"\n\t" -#define V_PMINUB_MMXEXT(mmr1, mmr2, mmrw) "pminub "mmr2", "mmr1"\n\t" -#define V_PMINUB_3DNOW(mmr1, mmr2, mmrw) V_PMINUB_MMX(mmr1, mmr2, mmrw) // use MMX version -#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SIMD_TYPE) -#define V_PMINUB2(mmr1, mmr2, mmrw, simd_type) V_PMINUB3(mmr1, mmr2, mmrw, simd_type) -#define V_PMINUB3(mmr1, mmr2, mmrw, simd_type) V_PMINUB_##simd_type(mmr1, mmr2, mmrw) - -// some macros for movntq instruction -// V_MOVNTQ(mmr1, mmr2) -#define V_MOVNTQ_MMX(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ_3DNOW(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ_MMXEXT(mmr1, mmr2) "movntq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SIMD_TYPE) -#define V_MOVNTQ2(mmr1, mmr2, simd_type) V_MOVNTQ3(mmr1, mmr2, simd_type) -#define V_MOVNTQ3(mmr1, mmr2, simd_type) V_MOVNTQ_##simd_type(mmr1, mmr2) - -// end of macros - -#ifdef IS_SSE2 - -#define MERGE4PIXavg(PADDR1, PADDR2) \ - "movdqu "PADDR1", %%xmm0\n\t" /* our 4 pixels */ \ - "movdqu "PADDR2", %%xmm1\n\t" /* our pixel2 value */ \ - "movdqa %%xmm0, %%xmm2\n\t" /* another copy of our pixel1 value */ \ - "movdqa %%xmm1, %%xmm3\n\t" /* another copy of our pixel1 value */ \ - "psubusb %%xmm1, %%xmm2\n\t" \ - "psubusb %%xmm0, %%xmm3\n\t" \ - "por %%xmm3, %%xmm2\n\t" \ - "pavgb %%xmm1, %%xmm0\n\t" /* avg of 2 pixels */ \ - "movdqa %%xmm2, %%xmm3\n\t" /* another copy of our our weights */ \ - "pxor %%xmm1, %%xmm1\n\t" \ - "psubusb %%xmm7, %%xmm3\n\t" /* nonzero where old weights lower, else 0 */ \ - "pcmpeqb %%xmm1, %%xmm3\n\t" /* now ff where new better, else 00 */ \ - "pcmpeqb %%xmm3, %%xmm1\n\t" /* here ff where old better, else 00 */ \ - "pand %%xmm3, %%xmm0\n\t" /* keep only better new pixels */ \ - "pand %%xmm3, %%xmm2\n\t" /* and weights */ \ - "pand %%xmm1, %%xmm5\n\t" /* keep only better old pixels */ \ - "pand %%xmm1, %%xmm7\n\t" \ - "por %%xmm0, %%xmm5\n\t" /* and merge new & old vals */ \ - "por %%xmm2, %%xmm7\n\t" - -#define MERGE4PIXavgH(PADDR1A, PADDR1B, PADDR2A, PADDR2B) \ - "movdqu "PADDR1A", %%xmm0\n\t" /* our 4 pixels */ \ - "movdqu "PADDR2A", %%xmm1\n\t" /* our pixel2 value */ \ - "movdqu "PADDR1B", %%xmm2\n\t" /* our 4 pixels */ \ - "movdqu "PADDR2B", %%xmm3\n\t" /* our pixel2 value */ \ - "pavgb %%xmm2, %%xmm0\n\t" \ - "pavgb %%xmm3, %%xmm1\n\t" \ - "movdqa %%xmm0, %%xmm2\n\t" /* another copy of our pixel1 value */ \ - "movdqa %%xmm1, %%xmm3\n\t" /* another copy of our pixel1 value */ \ - "psubusb %%xmm1, %%xmm2\n\t" \ - "psubusb %%xmm0, %%xmm3\n\t" \ - "por %%xmm3, %%xmm2\n\t" \ - "pavgb %%xmm1, %%xmm0\n\t" /* avg of 2 pixels */ \ - "movdqa %%xmm2, %%xmm3\n\t" /* another copy of our our weights */ \ - "pxor %%xmm1, %%xmm1\n\t" \ - "psubusb %%xmm7, %%xmm3\n\t" /* nonzero where old weights lower, else 0 */ \ - "pcmpeqb %%xmm1, %%xmm3\n\t" /* now ff where new better, else 00 */ \ - "pcmpeqb %%xmm3, %%xmm1\n\t" /* here ff where old better, else 00 */ \ - "pand %%xmm3, %%xmm0\n\t" /* keep only better new pixels */ \ - "pand %%xmm3, %%xmm2\n\t" /* and weights */ \ - "pand %%xmm1, %%xmm5\n\t" /* keep only better old pixels */ \ - "pand %%xmm1, %%xmm7\n\t" \ - "por %%xmm0, %%xmm5\n\t" /* and merge new & old vals */ \ - "por %%xmm2, %%xmm7\n\t" - -#define RESET_CHROMA "por "_UVMask", %%xmm7\n\t" - -#else // ifdef IS_SSE2 - -#define MERGE4PIXavg(PADDR1, PADDR2) \ - "movq "PADDR1", %%mm0\n\t" /* our 4 pixels */ \ - "movq "PADDR2", %%mm1\n\t" /* our pixel2 value */ \ - "movq %%mm0, %%mm2\n\t" /* another copy of our pixel1 value */ \ - "movq %%mm1, %%mm3\n\t" /* another copy of our pixel1 value */ \ - "psubusb %%mm1, %%mm2\n\t" \ - "psubusb %%mm0, %%mm3\n\t" \ - "por %%mm3, %%mm2\n\t" \ - V_PAVGB ("%%mm0", "%%mm1", "%%mm3", _ShiftMask) /* avg of 2 pixels */ \ - "movq %%mm2, %%mm3\n\t" /* another copy of our our weights */ \ - "pxor %%mm1, %%mm1\n\t" \ - "psubusb %%mm7, %%mm3\n\t" /* nonzero where old weights lower, else 0 */ \ - "pcmpeqb %%mm1, %%mm3\n\t" /* now ff where new better, else 00 */ \ - "pcmpeqb %%mm3, %%mm1\n\t" /* here ff where old better, else 00 */ \ - "pand %%mm3, %%mm0\n\t" /* keep only better new pixels */ \ - "pand %%mm3, %%mm2\n\t" /* and weights */ \ - "pand %%mm1, %%mm5\n\t" /* keep only better old pixels */ \ - "pand %%mm1, %%mm7\n\t" \ - "por %%mm0, %%mm5\n\t" /* and merge new & old vals */ \ - "por %%mm2, %%mm7\n\t" - -#define MERGE4PIXavgH(PADDR1A, PADDR1B, PADDR2A, PADDR2B) \ - "movq "PADDR1A", %%mm0\n\t" /* our 4 pixels */ \ - "movq "PADDR2A", %%mm1\n\t" /* our pixel2 value */ \ - "movq "PADDR1B", %%mm2\n\t" /* our 4 pixels */ \ - "movq "PADDR2B", %%mm3\n\t" /* our pixel2 value */ \ - V_PAVGB("%%mm0", "%%mm2", "%%mm2", _ShiftMask) \ - V_PAVGB("%%mm1", "%%mm3", "%%mm3", _ShiftMask) \ - "movq %%mm0, %%mm2\n\t" /* another copy of our pixel1 value */ \ - "movq %%mm1, %%mm3\n\t" /* another copy of our pixel1 value */ \ - "psubusb %%mm1, %%mm2\n\t" \ - "psubusb %%mm0, %%mm3\n\t" \ - "por %%mm3, %%mm2\n\t" \ - V_PAVGB("%%mm0", "%%mm1", "%%mm3", _ShiftMask) /* avg of 2 pixels */ \ - "movq %%mm2, %%mm3\n\t" /* another copy of our our weights */ \ - "pxor %%mm1, %%mm1\n\t" \ - "psubusb %%mm7, %%mm3\n\t" /* nonzero where old weights lower, else 0 */ \ - "pcmpeqb %%mm1, %%mm3\n\t" /* now ff where new better, else 00 */ \ - "pcmpeqb %%mm3, %%mm1\n\t" /* here ff where old better, else 00 */ \ - "pand %%mm3, %%mm0\n\t" /* keep only better new pixels */ \ - "pand %%mm3, %%mm2\n\t" /* and weights */ \ - "pand %%mm1, %%mm5\n\t" /* keep only better old pixels */ \ - "pand %%mm1, %%mm7\n\t" \ - "por %%mm0, %%mm5\n\t" /* and merge new & old vals */ \ - "por %%mm2, %%mm7\n\t" - -#define RESET_CHROMA "por "_UVMask", %%mm7\n\t" - -#endif - - diff --git a/gst/deinterlace2/tvtime/vfir.c b/gst/deinterlace2/tvtime/vfir.c deleted file mode 100644 index 56950459..00000000 --- a/gst/deinterlace2/tvtime/vfir.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * - * GStreamer - * Copyright (C) 2004 Billy Biggs - * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * This file contains code from ffmpeg, see http://ffmpeg.org/ (LGPL) - * and modifications by Billy Biggs. - * - * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs. - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_VFIR (gst_deinterlace_method_vfir_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR)) -#define GST_IS_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR)) -#define GST_DEINTERLACE_METHOD_VFIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass)) -#define GST_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIR)) -#define GST_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass)) -#define GST_DEINTERLACE_METHOD_VFIR_CAST(obj) ((GstDeinterlaceMethodVFIR*)(obj)) - -GType gst_deinterlace_method_vfir_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodVFIR; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodVFIRClass; - -/* - * 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]. - */ - -/** - * C implementation. - */ -static inline void -deinterlace_line_c (GstDeinterlaceMethod * self, GstDeinterlace2 * parent, - guint8 * dst, GstDeinterlaceScanlineData * scanlines, gint width) -{ - gint sum; - guint8 *lum_m4 = scanlines->tt1; - guint8 *lum_m3 = scanlines->t0; - guint8 *lum_m2 = scanlines->m1; - guint8 *lum_m1 = scanlines->b0; - guint8 *lum = scanlines->bb1; - gint size = width * 2; - - 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++; - } -} - -#ifdef BUILD_X86_ASM -#include "mmx.h" -static void -deinterlace_line_mmx (GstDeinterlaceMethod * self, GstDeinterlace2 * parent, - guint8 * dst, GstDeinterlaceScanlineData * scanlines, gint width) -{ - mmx_t rounder; - guint8 *lum_m4 = scanlines->tt1; - guint8 *lum_m3 = scanlines->t0; - guint8 *lum_m2 = scanlines->m1; - guint8 *lum_m1 = scanlines->b0; - guint8 *lum = scanlines->bb1; - - 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 (; width > 1; width -= 2) { - movd_m2r (*lum_m4, mm0); - movd_m2r (*lum_m3, mm1); - movd_m2r (*lum_m2, mm2); - movd_m2r (*lum_m1, mm3); - movd_m2r (*lum, 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); - lum_m4 += 4; - lum_m3 += 4; - lum_m2 += 4; - lum_m1 += 4; - lum += 4; - dst += 4; - } - emms (); - - /* Handle odd widths */ - if (width > 0) { - scanlines->tt1 = lum_m4; - scanlines->t0 = lum_m3; - scanlines->m1 = lum_m2; - scanlines->b0 = lum_m1; - scanlines->bb1 = lum; - - deinterlace_line_c (self, parent, dst, scanlines, width); - } -} -#endif - -G_DEFINE_TYPE (GstDeinterlaceMethodVFIR, gst_deinterlace_method_vfir, - GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void -gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; -#ifdef BUILD_X86_ASM - guint cpu_flags = oil_cpu_get_flags (); -#endif - - dim_class->fields_required = 2; - dim_class->name = "Blur Vertical"; - dim_class->nick = "vfir"; - dim_class->latency = 0; - -#ifdef BUILD_X86_ASM - if (cpu_flags & OIL_IMPL_FLAG_MMX) { - dism_class->interpolate_scanline = deinterlace_line_mmx; - } else { - dism_class->interpolate_scanline = deinterlace_line_c; - } -#else - dism_class->interpolate_scanline = deinterlace_line_c; -#endif -} - -static void -gst_deinterlace_method_vfir_init (GstDeinterlaceMethodVFIR * self) -{ -} diff --git a/gst/deinterlace2/tvtime/weave.c b/gst/deinterlace2/tvtime/weave.c deleted file mode 100644 index 09732a3a..00000000 --- a/gst/deinterlace2/tvtime/weave.c +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Weave frames - * Copyright (C) 2002 Billy Biggs . - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_WEAVE (gst_deinterlace_method_weave_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_WEAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE)) -#define GST_IS_DEINTERLACE_METHOD_WEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE)) -#define GST_DEINTERLACE_METHOD_WEAVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE, GstDeinterlaceMethodWeaveClass)) -#define GST_DEINTERLACE_METHOD_WEAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE, GstDeinterlaceMethodWeave)) -#define GST_DEINTERLACE_METHOD_WEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE, GstDeinterlaceMethodWeaveClass)) -#define GST_DEINTERLACE_METHOD_WEAVE_CAST(obj) ((GstDeinterlaceMethodWeave*)(obj)) - -GType gst_deinterlace_method_weave_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeave; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveClass; - - -static void -deinterlace_scanline_weave (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->m1, parent->row_stride); -} - -static void -copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace2 * parent, - guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->m0, parent->row_stride); -} - -G_DEFINE_TYPE (GstDeinterlaceMethodWeave, gst_deinterlace_method_weave, - GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void -gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; - - dim_class->fields_required = 2; - dim_class->name = "Weave"; - dim_class->nick = "weave"; - dim_class->latency = 0; - - dism_class->interpolate_scanline = deinterlace_scanline_weave; - dism_class->copy_scanline = copy_scanline; -} - -static void -gst_deinterlace_method_weave_init (GstDeinterlaceMethodWeave * self) -{ -} diff --git a/gst/deinterlace2/tvtime/weavebff.c b/gst/deinterlace2/tvtime/weavebff.c deleted file mode 100644 index 4ddf5a51..00000000 --- a/gst/deinterlace2/tvtime/weavebff.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Weave frames, bottom-field-first. - * Copyright (C) 2003 Billy Biggs . - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF (gst_deinterlace_method_weave_bff_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_WEAVE_BFF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF)) -#define GST_IS_DEINTERLACE_METHOD_WEAVE_BFF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF)) -#define GST_DEINTERLACE_METHOD_WEAVE_BFF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF, GstDeinterlaceMethodWeaveBFFClass)) -#define GST_DEINTERLACE_METHOD_WEAVE_BFF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF, GstDeinterlaceMethodWeaveBFF)) -#define GST_DEINTERLACE_METHOD_WEAVE_BFF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_BFF, GstDeinterlaceMethodWeaveBFFClass)) -#define GST_DEINTERLACE_METHOD_WEAVE_BFF_CAST(obj) ((GstDeinterlaceMethodWeaveBFF*)(obj)) - -GType gst_deinterlace_method_weave_bff_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeaveBFF; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveBFFClass; - - -static void -deinterlace_scanline_weave (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->m1, parent->row_stride); -} - -static void -copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace2 * parent, - guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width) -{ - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - oil_memcpy (out, scanlines->bb2, parent->row_stride); - } else { - oil_memcpy (out, scanlines->bb0, parent->row_stride); - } -} - -G_DEFINE_TYPE (GstDeinterlaceMethodWeaveBFF, gst_deinterlace_method_weave_bff, - GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void -gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass * - klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; - - dim_class->fields_required = 3; - dim_class->name = "Progressive: Bottom Field First"; - dim_class->nick = "weavebff"; - dim_class->latency = 0; - - dism_class->interpolate_scanline = deinterlace_scanline_weave; - dism_class->copy_scanline = copy_scanline; -} - -static void -gst_deinterlace_method_weave_bff_init (GstDeinterlaceMethodWeaveBFF * self) -{ -} diff --git a/gst/deinterlace2/tvtime/weavetff.c b/gst/deinterlace2/tvtime/weavetff.c deleted file mode 100644 index 9411f51b..00000000 --- a/gst/deinterlace2/tvtime/weavetff.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Weave frames, top-field-first. - * Copyright (C) 2003 Billy Biggs . - * Copyright (C) 2008 Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "_stdint.h" -#include "gstdeinterlace2.h" -#include - -#define GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF (gst_deinterlace_method_weave_tff_get_type ()) -#define GST_IS_DEINTERLACE_METHOD_WEAVE_TFF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF)) -#define GST_IS_DEINTERLACE_METHOD_WEAVE_TFF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF)) -#define GST_DEINTERLACE_METHOD_WEAVE_TFF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF, GstDeinterlaceMethodWeaveTFFClass)) -#define GST_DEINTERLACE_METHOD_WEAVE_TFF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF, GstDeinterlaceMethodWeaveTFF)) -#define GST_DEINTERLACE_METHOD_WEAVE_TFF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_WEAVE_TFF, GstDeinterlaceMethodWeaveTFFClass)) -#define GST_DEINTERLACE_METHOD_WEAVE_TFF_CAST(obj) ((GstDeinterlaceMethodWeaveTFF*)(obj)) - -GType gst_deinterlace_method_weave_tff_get_type (void); - -typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeaveTFF; - -typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveTFFClass; - - -static void -deinterlace_scanline_weave (GstDeinterlaceMethod * self, - GstDeinterlace2 * parent, guint8 * out, - GstDeinterlaceScanlineData * scanlines, gint width) -{ - oil_memcpy (out, scanlines->m1, parent->row_stride); -} - -static void -copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace2 * parent, - guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width) -{ - /* FIXME: original code used m2 and m0 but this looks really bad */ - if (scanlines->bottom_field) { - oil_memcpy (out, scanlines->bb0, parent->row_stride); - } else { - oil_memcpy (out, scanlines->bb2, parent->row_stride); - } -} - -G_DEFINE_TYPE (GstDeinterlaceMethodWeaveTFF, gst_deinterlace_method_weave_tff, - GST_TYPE_DEINTERLACE_SIMPLE_METHOD); - -static void -gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass * - klass) -{ - GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; - GstDeinterlaceSimpleMethodClass *dism_class = - (GstDeinterlaceSimpleMethodClass *) klass; - - dim_class->fields_required = 3; - dim_class->name = "Progressive: Top Field First"; - dim_class->nick = "weavetff"; - dim_class->latency = 0; - - dism_class->interpolate_scanline = deinterlace_scanline_weave; - dism_class->copy_scanline = copy_scanline; -} - -static void -gst_deinterlace_method_weave_tff_init (GstDeinterlaceMethodWeaveTFF * self) -{ -} diff --git a/gst/deinterlace2/tvtime/x86-64_macros.inc b/gst/deinterlace2/tvtime/x86-64_macros.inc deleted file mode 100644 index 2e9df758..00000000 --- a/gst/deinterlace2/tvtime/x86-64_macros.inc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * GStreamer - * Copyright (C) 2004 Dirk Ziegelmeier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * - * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578 - */ - -/* - * This file is copied from TVTIME's sources. - * Original author: Achim Schneider - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifndef XAX - -#if defined (HAVE_CPU_I386) && !defined(HAVE_CPU_X86_64) - -#define XAX "eax" -#define XBX "ebx" -#define XCX "ecx" -#define XDX "edx" -#define XSI "esi" -#define XDI "edi" -#define XSP "esp" -#define MOVX "movl" -#define LEAX "leal" -#define DECX "decl" -#define PUSHX "pushl" -#define POPX "popl" -#define CMPX "cmpl" -#define ADDX "addl" -#define SHLX "shll" -#define SHRX "shrl" -#define SUBX "subl" - -#elif defined (HAVE_CPU_X86_64) - -#define XAX "rax" -#define XBX "rbx" -#define XCX "rcx" -#define XDX "rdx" -#define XSI "rsi" -#define XDI "rdi" -#define XSP "rsp" -#define MOVX "movq" -#define LEAX "leaq" -#define DECX "decq" -#define PUSHX "pushq" -#define POPX "popq" -#define CMPX "cmpq" -#define ADDX "addq" -#define SHLX "shlq" -#define SHRX "shrq" -#define SUBX "subq" - -#else -#error Undefined architecture. Define either ARCH_X86 or ARCH_X86_64. -#endif - -#endif -- cgit