summaryrefslogtreecommitdiff
path: root/gst/yadif
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2013-02-07 15:09:51 -0800
committerDavid Schleef <ds@schleef.org>2013-02-11 12:30:29 -0800
commitb339812c07501a79bafa0c347ba918bf541edac0 (patch)
tree5b7c11ebd2b5c1de13683f694eff3d11f58e6d27 /gst/yadif
parent10b44cc81b4d54a9a4883246832d82402af700da (diff)
downloadgstreamer-plugins-bad-b339812c07501a79bafa0c347ba918bf541edac0.tar.gz
yadif: Add YADIF deinterlacing filter
Code copied from Libav, commit 26e4f0c70. Will eventually be moved to -ugly because underlying code is GPL.
Diffstat (limited to 'gst/yadif')
-rw-r--r--gst/yadif/Makefile.am22
-rw-r--r--gst/yadif/gstyadif.c493
-rw-r--r--gst/yadif/gstyadif.h64
-rw-r--r--gst/yadif/vf_yadif.c161
-rw-r--r--gst/yadif/yadif.c109
-rw-r--r--gst/yadif/yadif_template.c262
6 files changed, 1111 insertions, 0 deletions
diff --git a/gst/yadif/Makefile.am b/gst/yadif/Makefile.am
new file mode 100644
index 000000000..c01afc727
--- /dev/null
+++ b/gst/yadif/Makefile.am
@@ -0,0 +1,22 @@
+plugin_LTLIBRARIES = libgstyadif.la
+
+libgstyadif_la_SOURCES = gstyadif.c gstyadif.h vf_yadif.c yadif.c
+libgstyadif_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+libgstyadif_la_LIBADD = -lgstvideo-1.0 $(GST_BASE_LIBS) $(GST_LIBS)
+libgstyadif_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstyadif_la_LIBTOOLFLAGS = --tag=disable-static
+
+
+Android.mk: Makefile.am $(BUILT_SOURCES)
+ androgenizer \
+ -:PROJECT libgstyadif -:SHARED libgstyadif \
+ -:TAGS eng debug \
+ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
+ -:SOURCES $(libgstyadif_la_SOURCES) \
+ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstyadif_la_CFLAGS) \
+ -:LDFLAGS $(libgstyadif_la_LDFLAGS) \
+ $(libgstyadif_la_LIBADD) \
+ -ldl \
+ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
+ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+ > $@
diff --git a/gst/yadif/gstyadif.c b/gst/yadif/gstyadif.c
new file mode 100644
index 000000000..cde918432
--- /dev/null
+++ b/gst/yadif/gstyadif.c
@@ -0,0 +1,493 @@
+/* GStreamer
+ * Copyright (C) 2013 David Schleef <ds@schleef.org>
+ * Copyright (C) 2013 Rdio, Inc. <ingestions@rd.io>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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 General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+/**
+ * SECTION:element-gstyadif
+ *
+ * The yadif element deinterlaces video, using the YADIF deinterlacing
+ * filter copied from Libav. This element only handles the simple case
+ * of interlaced-mode=interleaved video instead of the more complex
+ * inverse telecine and deinterlace cases that are handled by the
+ * deinterlace element.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v videotestsrc pattern=ball ! interlace ! yadif ! xvimagesink
+ * ]|
+ * This pipeline creates an interlaced test pattern, and then deinterlaces
+ * it using the yadif filter.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/video/video.h>
+#include "gstyadif.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_yadif_debug_category);
+#define GST_CAT_DEFAULT gst_yadif_debug_category
+
+/* prototypes */
+
+
+static void gst_yadif_set_property (GObject * object,
+ guint property_id, const GValue * value, GParamSpec * pspec);
+static void gst_yadif_get_property (GObject * object,
+ guint property_id, GValue * value, GParamSpec * pspec);
+static void gst_yadif_dispose (GObject * object);
+static void gst_yadif_finalize (GObject * object);
+
+static GstCaps *gst_yadif_transform_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter);
+static GstCaps *gst_yadif_fixate_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
+static gboolean gst_yadif_accept_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps);
+static gboolean gst_yadif_set_caps (GstBaseTransform * trans, GstCaps * incaps,
+ GstCaps * outcaps);
+static gboolean gst_yadif_query (GstBaseTransform * trans,
+ GstPadDirection direction, GstQuery * query);
+static gboolean gst_yadif_decide_allocation (GstBaseTransform * trans,
+ GstQuery * query);
+static gboolean gst_yadif_filter_meta (GstBaseTransform * trans,
+ GstQuery * query, GType api, const GstStructure * params);
+static gboolean gst_yadif_propose_allocation (GstBaseTransform * trans,
+ GstQuery * decide_query, GstQuery * query);
+static gboolean gst_yadif_transform_size (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, gsize size, GstCaps * othercaps,
+ gsize * othersize);
+static gboolean gst_yadif_get_unit_size (GstBaseTransform * trans,
+ GstCaps * caps, gsize * size);
+static gboolean gst_yadif_start (GstBaseTransform * trans);
+static gboolean gst_yadif_stop (GstBaseTransform * trans);
+static gboolean gst_yadif_sink_event (GstBaseTransform * trans,
+ GstEvent * event);
+static gboolean gst_yadif_src_event (GstBaseTransform * trans,
+ GstEvent * event);
+static GstFlowReturn gst_yadif_prepare_output_buffer (GstBaseTransform * trans,
+ GstBuffer * input, GstBuffer ** outbuf);
+static gboolean gst_yadif_copy_metadata (GstBaseTransform * trans,
+ GstBuffer * input, GstBuffer * outbuf);
+static gboolean gst_yadif_transform_meta (GstBaseTransform * trans,
+ GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf);
+static void gst_yadif_before_transform (GstBaseTransform * trans,
+ GstBuffer * buffer);
+static GstFlowReturn gst_yadif_transform (GstBaseTransform * trans,
+ GstBuffer * inbuf, GstBuffer * outbuf);
+static GstFlowReturn gst_yadif_transform_ip (GstBaseTransform * trans,
+ GstBuffer * buf);
+
+enum
+{
+ PROP_0
+};
+
+/* pad templates */
+
+static GstStaticPadTemplate gst_yadif_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{Y42B,I420,Y444}")
+ ",interlace-mode=(string){interleaved,mixed,progressive}")
+ );
+
+static GstStaticPadTemplate gst_yadif_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{Y42B,I420,Y444}")
+ ",interlace-mode=(string)progressive")
+ );
+
+
+/* class initialization */
+
+G_DEFINE_TYPE_WITH_CODE (GstYadif, gst_yadif, GST_TYPE_BASE_TRANSFORM,
+ GST_DEBUG_CATEGORY_INIT (gst_yadif_debug_category, "yadif", 0,
+ "debug category for yadif element"));
+
+static void
+gst_yadif_class_init (GstYadifClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseTransformClass *base_transform_class =
+ GST_BASE_TRANSFORM_CLASS (klass);
+
+ /* Setting up pads and setting metadata should be moved to
+ base_class_init if you intend to subclass this class. */
+ gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
+ gst_static_pad_template_get (&gst_yadif_sink_template));
+ gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
+ gst_static_pad_template_get (&gst_yadif_src_template));
+
+ gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
+ "YADIF deinterlacer", "Video/Filter",
+ "Deinterlace video using YADIF filter", "David Schleef <ds@schleef.org>");
+
+ gobject_class->set_property = gst_yadif_set_property;
+ gobject_class->get_property = gst_yadif_get_property;
+ gobject_class->dispose = gst_yadif_dispose;
+ gobject_class->finalize = gst_yadif_finalize;
+ base_transform_class->transform_caps =
+ GST_DEBUG_FUNCPTR (gst_yadif_transform_caps);
+ if (0)
+ base_transform_class->fixate_caps =
+ GST_DEBUG_FUNCPTR (gst_yadif_fixate_caps);
+ if (0)
+ base_transform_class->accept_caps =
+ GST_DEBUG_FUNCPTR (gst_yadif_accept_caps);
+ base_transform_class->set_caps = GST_DEBUG_FUNCPTR (gst_yadif_set_caps);
+ if (0)
+ base_transform_class->query = GST_DEBUG_FUNCPTR (gst_yadif_query);
+ if (0)
+ base_transform_class->decide_allocation =
+ GST_DEBUG_FUNCPTR (gst_yadif_decide_allocation);
+ if (0)
+ base_transform_class->filter_meta =
+ GST_DEBUG_FUNCPTR (gst_yadif_filter_meta);
+ if (0)
+ base_transform_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_yadif_propose_allocation);
+ if (0)
+ base_transform_class->transform_size =
+ GST_DEBUG_FUNCPTR (gst_yadif_transform_size);
+ base_transform_class->get_unit_size =
+ GST_DEBUG_FUNCPTR (gst_yadif_get_unit_size);
+ base_transform_class->start = GST_DEBUG_FUNCPTR (gst_yadif_start);
+ base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_yadif_stop);
+ if (0)
+ base_transform_class->sink_event = GST_DEBUG_FUNCPTR (gst_yadif_sink_event);
+ if (0)
+ base_transform_class->src_event = GST_DEBUG_FUNCPTR (gst_yadif_src_event);
+ if (0)
+ base_transform_class->prepare_output_buffer =
+ GST_DEBUG_FUNCPTR (gst_yadif_prepare_output_buffer);
+ if (0)
+ base_transform_class->copy_metadata =
+ GST_DEBUG_FUNCPTR (gst_yadif_copy_metadata);
+ if (0)
+ base_transform_class->transform_meta =
+ GST_DEBUG_FUNCPTR (gst_yadif_transform_meta);
+ if (0)
+ base_transform_class->before_transform =
+ GST_DEBUG_FUNCPTR (gst_yadif_before_transform);
+ base_transform_class->transform = GST_DEBUG_FUNCPTR (gst_yadif_transform);
+ if (0)
+ base_transform_class->transform_ip =
+ GST_DEBUG_FUNCPTR (gst_yadif_transform_ip);
+
+}
+
+static void
+gst_yadif_init (GstYadif * yadif)
+{
+
+ yadif->sinkpad = gst_pad_new_from_static_template (&gst_yadif_sink_template,
+ "sink");
+
+ yadif->srcpad = gst_pad_new_from_static_template (&gst_yadif_src_template,
+ "src");
+}
+
+void
+gst_yadif_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ /* GstYadif *yadif = GST_YADIF (object); */
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_yadif_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ /* GstYadif *yadif = GST_YADIF (object); */
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_yadif_dispose (GObject * object)
+{
+ /* GstYadif *yadif = GST_YADIF (object); */
+
+ /* clean up as possible. may be called multiple times */
+
+ G_OBJECT_CLASS (gst_yadif_parent_class)->dispose (object);
+}
+
+void
+gst_yadif_finalize (GObject * object)
+{
+ /* GstYadif *yadif = GST_YADIF (object); */
+
+ /* clean up object here */
+
+ G_OBJECT_CLASS (gst_yadif_parent_class)->finalize (object);
+}
+
+
+static GstCaps *
+gst_yadif_transform_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+ GstCaps *othercaps;
+
+ othercaps = gst_caps_copy (caps);
+
+ if (direction == GST_PAD_SRC) {
+ GValue value = G_VALUE_INIT;
+ GValue v = G_VALUE_INIT;
+
+ g_value_init (&value, GST_TYPE_LIST);
+ g_value_init (&v, G_TYPE_STRING);
+
+ g_value_set_string (&v, "interleaved");
+ gst_value_list_append_value (&value, &v);
+ g_value_set_string (&v, "mixed");
+ gst_value_list_append_value (&value, &v);
+ g_value_set_string (&v, "progressive");
+ gst_value_list_append_value (&value, &v);
+
+ gst_caps_set_value (othercaps, "interlace-mode", &value);
+ g_value_reset (&value);
+ g_value_reset (&v);
+ } else {
+ gst_caps_set_simple (othercaps, "interlace-mode", G_TYPE_STRING,
+ "progressive", NULL);
+ }
+
+ return othercaps;
+}
+
+static GstCaps *
+gst_yadif_fixate_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
+{
+
+ return NULL;
+}
+
+static gboolean
+gst_yadif_accept_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps)
+{
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_set_caps (GstBaseTransform * trans, GstCaps * incaps,
+ GstCaps * outcaps)
+{
+ GstYadif *yadif = GST_YADIF (trans);
+
+ gst_video_info_from_caps (&yadif->video_info, incaps);
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_query (GstBaseTransform * trans, GstPadDirection direction,
+ GstQuery * query)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_decide_allocation (GstBaseTransform * trans, GstQuery * query)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_filter_meta (GstBaseTransform * trans, GstQuery * query,
+ GType api, const GstStructure * params)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_propose_allocation (GstBaseTransform * trans,
+ GstQuery * decide_query, GstQuery * query)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_transform_size (GstBaseTransform * trans,
+ GstPadDirection direction,
+ GstCaps * caps, gsize size, GstCaps * othercaps, gsize * othersize)
+{
+
+ return FALSE;
+}
+
+static gboolean
+gst_yadif_get_unit_size (GstBaseTransform * trans, GstCaps * caps, gsize * size)
+{
+ GstVideoInfo info;
+
+ if (gst_video_info_from_caps (&info, caps)) {
+ *size = GST_VIDEO_INFO_SIZE (&info);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+gst_yadif_start (GstBaseTransform * trans)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_stop (GstBaseTransform * trans)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_sink_event (GstBaseTransform * trans, GstEvent * event)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_src_event (GstBaseTransform * trans, GstEvent * event)
+{
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_yadif_prepare_output_buffer (GstBaseTransform * trans,
+ GstBuffer * input, GstBuffer ** buf)
+{
+
+ return GST_FLOW_ERROR;
+}
+
+static gboolean
+gst_yadif_copy_metadata (GstBaseTransform * trans,
+ GstBuffer * input, GstBuffer * outbuf)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_yadif_transform_meta (GstBaseTransform * trans,
+ GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf)
+{
+
+ return TRUE;
+}
+
+static void
+gst_yadif_before_transform (GstBaseTransform * trans, GstBuffer * buffer)
+{
+
+}
+
+void yadif_filter (GstYadif * yadif, int parity, int tff);
+
+static GstFlowReturn
+gst_yadif_transform (GstBaseTransform * trans, GstBuffer * inbuf,
+ GstBuffer * outbuf)
+{
+ GstYadif *yadif = GST_YADIF (trans);
+ int parity;
+ int tff;
+
+ parity = 0;
+ tff = 0;
+
+ if (!gst_video_frame_map (&yadif->dest_frame, &yadif->video_info, outbuf,
+ GST_MAP_WRITE))
+ goto dest_map_failed;
+
+ if (!gst_video_frame_map (&yadif->cur_frame, &yadif->video_info, inbuf,
+ GST_MAP_READ))
+ goto src_map_failed;
+
+ yadif->next_frame = yadif->cur_frame;
+ yadif->prev_frame = yadif->cur_frame;
+
+ yadif_filter (yadif, parity, tff);
+
+ gst_video_frame_unmap (&yadif->dest_frame);
+ gst_video_frame_unmap (&yadif->cur_frame);
+ return GST_FLOW_OK;
+
+dest_map_failed:
+ {
+ GST_ERROR_OBJECT (yadif, "failed to map dest");
+ return GST_FLOW_ERROR;
+ }
+src_map_failed:
+ {
+ GST_ERROR_OBJECT (yadif, "failed to map src");
+ gst_video_frame_unmap (&yadif->dest_frame);
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_yadif_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
+{
+
+ return GST_FLOW_OK;
+}
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+
+ return gst_element_register (plugin, "yadif", GST_RANK_NONE, GST_TYPE_YADIF);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ yadif,
+ "YADIF deinterlacing filter",
+ plugin_init, VERSION, "GPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/gst/yadif/gstyadif.h b/gst/yadif/gstyadif.h
new file mode 100644
index 000000000..118f5010d
--- /dev/null
+++ b/gst/yadif/gstyadif.h
@@ -0,0 +1,64 @@
+/* GStreamer
+ * Copyright (C) 2013 Rdio, Inc. <ingestions@rd.io>
+ * Copyright (C) 2013 David Schleef <ds@schleef.org>
+ *
+ * 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _GST_YADIF_H_
+#define _GST_YADIF_H_
+
+#include <gst/base/gstbasetransform.h>
+#include <gst/video/video.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_YADIF (gst_yadif_get_type())
+#define GST_YADIF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_YADIF,GstYadif))
+#define GST_YADIF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_YADIF,GstYadifClass))
+#define GST_IS_YADIF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_YADIF))
+#define GST_IS_YADIF_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_YADIF))
+
+typedef struct _GstYadif GstYadif;
+typedef struct _GstYadifClass GstYadifClass;
+
+struct _GstYadif
+{
+ GstBaseTransform base_yadif;
+
+ GstPad *sinkpad;
+ GstPad *srcpad;
+
+ int mode;
+
+ GstVideoInfo video_info;
+
+ GstVideoFrame prev_frame;
+ GstVideoFrame cur_frame;
+ GstVideoFrame next_frame;
+ GstVideoFrame dest_frame;
+};
+
+struct _GstYadifClass
+{
+ GstBaseTransformClass base_yadif_class;
+};
+
+GType gst_yadif_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gst/yadif/vf_yadif.c b/gst/yadif/vf_yadif.c
new file mode 100644
index 000000000..efb78843f
--- /dev/null
+++ b/gst/yadif/vf_yadif.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2013 David Schleef <ds@schleef.org>
+ * Copyright (C) 2013 Rdio, Inc. <ingestions@rd.io>
+ * Copyright (C) 2006-2010 Michael Niedermayer <michaelni@gmx.at>
+ * 2010 James Darnley <james.darnley@gmail.com>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Libav 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 Libav; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gstyadif.h>
+#include <string.h>
+
+#undef NDEBUG
+#include <assert.h>
+
+#define FFABS(a) ABS(a)
+#define FFMIN(a,b) MIN(a,b)
+#define FFMAX(a,b) MAX(a,b)
+#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
+#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
+
+
+#define PERM_RWP AV_PERM_WRITE | AV_PERM_PRESERVE | AV_PERM_REUSE
+
+#define CHECK(j)\
+ { int score = FFABS(cur[mrefs-1+(j)] - cur[prefs-1-(j)])\
+ + FFABS(cur[mrefs +(j)] - cur[prefs -(j)])\
+ + FFABS(cur[mrefs+1+(j)] - cur[prefs+1-(j)]);\
+ if (score < spatial_score) {\
+ spatial_score= score;\
+ spatial_pred= (cur[mrefs +(j)] + cur[prefs -(j)])>>1;\
+
+#define FILTER \
+ for (x = 0; x < w; x++) { \
+ int c = cur[mrefs]; \
+ int d = (prev2[0] + next2[0])>>1; \
+ int e = cur[prefs]; \
+ int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
+ int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e) )>>1; \
+ int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e) )>>1; \
+ int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); \
+ int spatial_pred = (c+e) >> 1; \
+ int spatial_score = FFABS(cur[mrefs - 1] - cur[prefs - 1]) + FFABS(c-e) \
+ + FFABS(cur[mrefs + 1] - cur[prefs + 1]) - 1; \
+ \
+ CHECK(-1) CHECK(-2) }} }} \
+ CHECK( 1) CHECK( 2) }} }} \
+ \
+ if (mode < 2) { \
+ int b = (prev2[2 * mrefs] + next2[2 * mrefs])>>1; \
+ int f = (prev2[2 * prefs] + next2[2 * prefs])>>1; \
+ int max = FFMAX3(d - e, d - c, FFMIN(b - c, f - e)); \
+ int min = FFMIN3(d - e, d - c, FFMAX(b - c, f - e)); \
+ \
+ diff = FFMAX3(diff, min, -max); \
+ } \
+ \
+ if (spatial_pred > d + diff) \
+ spatial_pred = d + diff; \
+ else if (spatial_pred < d - diff) \
+ spatial_pred = d - diff; \
+ \
+ dst[0] = spatial_pred; \
+ \
+ dst++; \
+ cur++; \
+ prev++; \
+ next++; \
+ prev2++; \
+ next2++; \
+ }
+
+static void
+filter_line_c (guint8 * dst,
+ guint8 * prev, guint8 * cur, guint8 * next,
+ int w, int prefs, int mrefs, int parity, int mode)
+{
+ int x;
+ guint8 *prev2 = parity ? prev : cur;
+ guint8 *next2 = parity ? cur : next;
+
+FILTER}
+
+#if 0
+static void
+filter_line_c_16bit (guint16 * dst,
+ guint16 * prev, guint16 * cur, guint16 * next,
+ int w, int prefs, int mrefs, int parity, int mode)
+{
+ int x;
+ guint16 *prev2 = parity ? prev : cur;
+ guint16 *next2 = parity ? cur : next;
+ mrefs /= 2;
+ prefs /= 2;
+
+FILTER}
+#endif
+
+void yadif_filter (GstYadif * yadif, int parity, int tff);
+void filter_line_x86 (guint8 * dst,
+ guint8 * prev, guint8 * cur, guint8 * next,
+ int w, int prefs, int mrefs, int parity, int mode);
+
+void
+yadif_filter (GstYadif * yadif, int parity, int tff)
+{
+ int y, i;
+ const GstVideoInfo *vi = &yadif->video_info;
+ const GstVideoFormatInfo *vfi = vi->finfo;
+
+ for (i = 0; i < GST_VIDEO_FORMAT_INFO_N_COMPONENTS (vfi); i++) {
+ int w = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vfi, i, vi->width);
+ int h = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vfi, i, vi->height);
+ int refs = GST_VIDEO_INFO_COMP_STRIDE (vi, i);
+ int df = GST_VIDEO_INFO_COMP_PSTRIDE (vi, i);
+ guint8 *prev_data = GST_VIDEO_FRAME_COMP_DATA (&yadif->prev_frame, i);
+ guint8 *cur_data = GST_VIDEO_FRAME_COMP_DATA (&yadif->cur_frame, i);
+ guint8 *next_data = GST_VIDEO_FRAME_COMP_DATA (&yadif->next_frame, i);
+ guint8 *dest_data = GST_VIDEO_FRAME_COMP_DATA (&yadif->dest_frame, i);
+
+ for (y = 0; y < h; y++) {
+ if ((y ^ parity) & 1) {
+ guint8 *prev = prev_data + y * refs;
+ guint8 *cur = cur_data + y * refs;
+ guint8 *next = next_data + y * refs;
+ guint8 *dst = dest_data + y * refs;
+ int mode = ((y == 1) || (y + 2 == h)) ? 2 : yadif->mode;
+ if (0) {
+ filter_line_c (dst, prev, cur, next, w,
+ y + 1 < h ? refs : -refs, y ? -refs : refs, parity ^ tff, mode);
+ } else {
+ filter_line_x86 (dst, prev, cur, next, w,
+ y + 1 < h ? refs : -refs, y ? -refs : refs, parity ^ tff, mode);
+ }
+ } else {
+ guint8 *dst = dest_data + y * refs;
+ guint8 *cur = cur_data + y * refs;
+
+ memcpy (dst, cur, w * df);
+ }
+ }
+ }
+
+#if 0
+ emms_c ();
+#endif
+}
diff --git a/gst/yadif/yadif.c b/gst/yadif/yadif.c
new file mode 100644
index 000000000..93b526d5b
--- /dev/null
+++ b/gst/yadif/yadif.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Libav 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 Libav; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <glib.h>
+#if 0
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/internal.h"
+#include "libavutil/mem.h"
+#include "libavutil/x86/asm.h"
+#include "libavcodec/x86/dsputil_mmx.h"
+#include "libavfilter/yadif.h"
+#endif
+
+//#if HAVE_INLINE_ASM
+
+typedef struct xmm_reg
+{
+ guint64 a, b;
+} xmm_reg;
+typedef gint64 x86_reg;
+#define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v
+#define DECLARE_ASM_CONST(n,t,v) static const t __attribute__((used)) __attribute__ ((aligned (n))) v
+
+#define ARCH_X86_64 1
+//#if ARCH_X86_64 && defined(__PIC__)
+#if 1
+# define LOCAL_MANGLE(a) #a "(%%rip)"
+#else
+# define LOCAL_MANGLE(a) #a
+#endif
+
+#define EXTERN_PREFIX ""
+#define MANGLE(a) EXTERN_PREFIX LOCAL_MANGLE(a)
+
+DECLARE_ASM_CONST (16, const xmm_reg, pb_1) = {
+0x0101010101010101ULL, 0x0101010101010101ULL};
+
+DECLARE_ASM_CONST (16, const xmm_reg, pw_1) = {
+0x0001000100010001ULL, 0x0001000100010001ULL};
+
+
+
+#if HAVE_SSSE3_INLINE
+#define COMPILE_TEMPLATE_SSE2 1
+#define COMPILE_TEMPLATE_SSSE3 1
+#undef RENAME
+#define RENAME(a) a ## _ssse3
+#include "yadif_template.c"
+#undef COMPILE_TEMPLATE_SSSE3
+#endif
+
+//#if HAVE_SSE2_INLINE
+#undef RENAME
+#define RENAME(a) a ## _sse2
+#include "yadif_template.c"
+#undef COMPILE_TEMPLATE_SSE2
+//#endif
+
+#if HAVE_MMXEXT_INLINE
+#undef RENAME
+#define RENAME(a) a ## _mmxext
+#include "yadif_template.c"
+#endif
+
+//#endif /* HAVE_INLINE_ASM */
+
+void filter_line_x86 (guint8 * dst,
+ guint8 * prev, guint8 * cur, guint8 * next,
+ int w, int prefs, int mrefs, int parity, int mode);
+
+void
+filter_line_x86 (guint8 * dst,
+ guint8 * prev, guint8 * cur, guint8 * next,
+ int w, int prefs, int mrefs, int parity, int mode)
+{
+#if 0
+#if HAVE_MMXEXT_INLINE
+ if (cpu_flags & AV_CPU_FLAG_MMXEXT)
+ yadif->filter_line = yadif_filter_line_mmxext;
+#endif
+#if HAVE_SSE2_INLINE
+ if (cpu_flags & AV_CPU_FLAG_SSE2)
+ yadif->filter_line = yadif_filter_line_sse2;
+#endif
+#if HAVE_SSSE3_INLINE
+ if (cpu_flags & AV_CPU_FLAG_SSSE3)
+ yadif->filter_line = yadif_filter_line_ssse3;
+#endif
+#endif
+ yadif_filter_line_sse2 (dst, prev, cur, next, w, prefs, mrefs, parity, mode);
+}
diff --git a/gst/yadif/yadif_template.c b/gst/yadif/yadif_template.c
new file mode 100644
index 000000000..ef3dffc9f
--- /dev/null
+++ b/gst/yadif/yadif_template.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Libav 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 Libav; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef COMPILE_TEMPLATE_SSE2
+#define MM "%%xmm"
+#define MOV "movq"
+#define MOVQ "movdqa"
+#define MOVQU "movdqu"
+#define STEP 8
+#define LOAD(mem,dst) \
+ MOV" "mem", "dst" \n\t"\
+ "punpcklbw "MM"7, "dst" \n\t"
+#define PSRL1(reg) "psrldq $1, "reg" \n\t"
+#define PSRL2(reg) "psrldq $2, "reg" \n\t"
+#define PSHUF(src,dst) "movdqa "dst", "src" \n\t"\
+ "psrldq $2, "src" \n\t"
+#else
+#define MM "%%mm"
+#define MOV "movd"
+#define MOVQ "movq"
+#define MOVQU "movq"
+#define STEP 4
+#define LOAD(mem,dst) \
+ MOV" "mem", "dst" \n\t"\
+ "punpcklbw "MM"7, "dst" \n\t"
+#define PSRL1(reg) "psrlq $8, "reg" \n\t"
+#define PSRL2(reg) "psrlq $16, "reg" \n\t"
+#define PSHUF(src,dst) "pshufw $9, "dst", "src" \n\t"
+#endif
+
+#ifdef COMPILE_TEMPLATE_SSSE3
+#define PABS(tmp,dst) \
+ "pabsw "dst", "dst" \n\t"
+#else
+#define PABS(tmp,dst) \
+ "pxor "tmp", "tmp" \n\t"\
+ "psubw "dst", "tmp" \n\t"\
+ "pmaxsw "tmp", "dst" \n\t"
+#endif
+
+#define CHECK(pj,mj) \
+ MOVQU" "#pj"(%[cur],%[mrefs]), "MM"2 \n\t" /* cur[x-refs-1+j] */\
+ MOVQU" "#mj"(%[cur],%[prefs]), "MM"3 \n\t" /* cur[x+refs-1-j] */\
+ MOVQ" "MM"2, "MM"4 \n\t"\
+ MOVQ" "MM"2, "MM"5 \n\t"\
+ "pxor "MM"3, "MM"4 \n\t"\
+ "pavgb "MM"3, "MM"5 \n\t"\
+ "pand "MANGLE(pb_1)", "MM"4 \n\t"\
+ "psubusb "MM"4, "MM"5 \n\t"\
+ PSRL1(MM"5") \
+ "punpcklbw "MM"7, "MM"5 \n\t" /* (cur[x-refs+j] + cur[x+refs-j])>>1 */\
+ MOVQ" "MM"2, "MM"4 \n\t"\
+ "psubusb "MM"3, "MM"2 \n\t"\
+ "psubusb "MM"4, "MM"3 \n\t"\
+ "pmaxub "MM"3, "MM"2 \n\t"\
+ MOVQ" "MM"2, "MM"3 \n\t"\
+ MOVQ" "MM"2, "MM"4 \n\t" /* ABS(cur[x-refs-1+j] - cur[x+refs-1-j]) */\
+ PSRL1(MM"3") /* ABS(cur[x-refs +j] - cur[x+refs -j]) */\
+ PSRL2(MM"4") /* ABS(cur[x-refs+1+j] - cur[x+refs+1-j]) */\
+ "punpcklbw "MM"7, "MM"2 \n\t"\
+ "punpcklbw "MM"7, "MM"3 \n\t"\
+ "punpcklbw "MM"7, "MM"4 \n\t"\
+ "paddw "MM"3, "MM"2 \n\t"\
+ "paddw "MM"4, "MM"2 \n\t" /* score */
+
+#define CHECK1 \
+ MOVQ" "MM"0, "MM"3 \n\t"\
+ "pcmpgtw "MM"2, "MM"3 \n\t" /* if(score < spatial_score) */\
+ "pminsw "MM"2, "MM"0 \n\t" /* spatial_score= score; */\
+ MOVQ" "MM"3, "MM"6 \n\t"\
+ "pand "MM"3, "MM"5 \n\t"\
+ "pandn "MM"1, "MM"3 \n\t"\
+ "por "MM"5, "MM"3 \n\t"\
+ MOVQ" "MM"3, "MM"1 \n\t" /* spatial_pred= (cur[x-refs+j] + cur[x+refs-j])>>1; */
+
+#define CHECK2 /* pretend not to have checked dir=2 if dir=1 was bad.\
+ hurts both quality and speed, but matches the C version. */\
+ "paddw "MANGLE(pw_1)", "MM"6 \n\t"\
+ "psllw $14, "MM"6 \n\t"\
+ "paddsw "MM"6, "MM"2 \n\t"\
+ MOVQ" "MM"0, "MM"3 \n\t"\
+ "pcmpgtw "MM"2, "MM"3 \n\t"\
+ "pminsw "MM"2, "MM"0 \n\t"\
+ "pand "MM"3, "MM"5 \n\t"\
+ "pandn "MM"1, "MM"3 \n\t"\
+ "por "MM"5, "MM"3 \n\t"\
+ MOVQ" "MM"3, "MM"1 \n\t"
+
+static void RENAME (yadif_filter_line) (guint8 * dst, guint8 * prev,
+ guint8 * cur, guint8 * next, int w, int prefs, int mrefs, int parity,
+ int mode)
+{
+ DECLARE_ALIGNED (16, guint8, tmp)[16 * 4];
+ int x;
+
+#define FILTER\
+ for(x=0; x<w; x+=STEP){\
+ __asm__ volatile(\
+ "pxor "MM"7, "MM"7 \n\t"\
+ LOAD("(%[cur],%[mrefs])", MM"0") /* c = cur[x-refs] */\
+ LOAD("(%[cur],%[prefs])", MM"1") /* e = cur[x+refs] */\
+ LOAD("(%["prev2"])", MM"2") /* prev2[x] */\
+ LOAD("(%["next2"])", MM"3") /* next2[x] */\
+ MOVQ" "MM"3, "MM"4 \n\t"\
+ "paddw "MM"2, "MM"3 \n\t"\
+ "psraw $1, "MM"3 \n\t" /* d = (prev2[x] + next2[x])>>1 */\
+ MOVQ" "MM"0, (%[tmp]) \n\t" /* c */\
+ MOVQ" "MM"3, 16(%[tmp]) \n\t" /* d */\
+ MOVQ" "MM"1, 32(%[tmp]) \n\t" /* e */\
+ "psubw "MM"4, "MM"2 \n\t"\
+ PABS( MM"4", MM"2") /* temporal_diff0 */\
+ LOAD("(%[prev],%[mrefs])", MM"3") /* prev[x-refs] */\
+ LOAD("(%[prev],%[prefs])", MM"4") /* prev[x+refs] */\
+ "psubw "MM"0, "MM"3 \n\t"\
+ "psubw "MM"1, "MM"4 \n\t"\
+ PABS( MM"5", MM"3")\
+ PABS( MM"5", MM"4")\
+ "paddw "MM"4, "MM"3 \n\t" /* temporal_diff1 */\
+ "psrlw $1, "MM"2 \n\t"\
+ "psrlw $1, "MM"3 \n\t"\
+ "pmaxsw "MM"3, "MM"2 \n\t"\
+ LOAD("(%[next],%[mrefs])", MM"3") /* next[x-refs] */\
+ LOAD("(%[next],%[prefs])", MM"4") /* next[x+refs] */\
+ "psubw "MM"0, "MM"3 \n\t"\
+ "psubw "MM"1, "MM"4 \n\t"\
+ PABS( MM"5", MM"3")\
+ PABS( MM"5", MM"4")\
+ "paddw "MM"4, "MM"3 \n\t" /* temporal_diff2 */\
+ "psrlw $1, "MM"3 \n\t"\
+ "pmaxsw "MM"3, "MM"2 \n\t"\
+ MOVQ" "MM"2, 48(%[tmp]) \n\t" /* diff */\
+\
+ "paddw "MM"0, "MM"1 \n\t"\
+ "paddw "MM"0, "MM"0 \n\t"\
+ "psubw "MM"1, "MM"0 \n\t"\
+ "psrlw $1, "MM"1 \n\t" /* spatial_pred */\
+ PABS( MM"2", MM"0") /* ABS(c-e) */\
+\
+ MOVQU" -1(%[cur],%[mrefs]), "MM"2 \n\t" /* cur[x-refs-1] */\
+ MOVQU" -1(%[cur],%[prefs]), "MM"3 \n\t" /* cur[x+refs-1] */\
+ MOVQ" "MM"2, "MM"4 \n\t"\
+ "psubusb "MM"3, "MM"2 \n\t"\
+ "psubusb "MM"4, "MM"3 \n\t"\
+ "pmaxub "MM"3, "MM"2 \n\t"\
+ PSHUF(MM"3", MM"2") \
+ "punpcklbw "MM"7, "MM"2 \n\t" /* ABS(cur[x-refs-1] - cur[x+refs-1]) */\
+ "punpcklbw "MM"7, "MM"3 \n\t" /* ABS(cur[x-refs+1] - cur[x+refs+1]) */\
+ "paddw "MM"2, "MM"0 \n\t"\
+ "paddw "MM"3, "MM"0 \n\t"\
+ "psubw "MANGLE(pw_1)", "MM"0 \n\t" /* spatial_score */\
+\
+ CHECK(-2,0)\
+ CHECK1\
+ CHECK(-3,1)\
+ CHECK2\
+ CHECK(0,-2)\
+ CHECK1\
+ CHECK(1,-3)\
+ CHECK2\
+\
+ /* if(p->mode<2) ... */\
+ MOVQ" 48(%[tmp]), "MM"6 \n\t" /* diff */\
+ "cmpl $2, %[mode] \n\t"\
+ "jge 1f \n\t"\
+ LOAD("(%["prev2"],%[mrefs],2)", MM"2") /* prev2[x-2*refs] */\
+ LOAD("(%["next2"],%[mrefs],2)", MM"4") /* next2[x-2*refs] */\
+ LOAD("(%["prev2"],%[prefs],2)", MM"3") /* prev2[x+2*refs] */\
+ LOAD("(%["next2"],%[prefs],2)", MM"5") /* next2[x+2*refs] */\
+ "paddw "MM"4, "MM"2 \n\t"\
+ "paddw "MM"5, "MM"3 \n\t"\
+ "psrlw $1, "MM"2 \n\t" /* b */\
+ "psrlw $1, "MM"3 \n\t" /* f */\
+ MOVQ" (%[tmp]), "MM"4 \n\t" /* c */\
+ MOVQ" 16(%[tmp]), "MM"5 \n\t" /* d */\
+ MOVQ" 32(%[tmp]), "MM"7 \n\t" /* e */\
+ "psubw "MM"4, "MM"2 \n\t" /* b-c */\
+ "psubw "MM"7, "MM"3 \n\t" /* f-e */\
+ MOVQ" "MM"5, "MM"0 \n\t"\
+ "psubw "MM"4, "MM"5 \n\t" /* d-c */\
+ "psubw "MM"7, "MM"0 \n\t" /* d-e */\
+ MOVQ" "MM"2, "MM"4 \n\t"\
+ "pminsw "MM"3, "MM"2 \n\t"\
+ "pmaxsw "MM"4, "MM"3 \n\t"\
+ "pmaxsw "MM"5, "MM"2 \n\t"\
+ "pminsw "MM"5, "MM"3 \n\t"\
+ "pmaxsw "MM"0, "MM"2 \n\t" /* max */\
+ "pminsw "MM"0, "MM"3 \n\t" /* min */\
+ "pxor "MM"4, "MM"4 \n\t"\
+ "pmaxsw "MM"3, "MM"6 \n\t"\
+ "psubw "MM"2, "MM"4 \n\t" /* -max */\
+ "pmaxsw "MM"4, "MM"6 \n\t" /* diff= MAX3(diff, min, -max); */\
+ "1: \n\t"\
+\
+ MOVQ" 16(%[tmp]), "MM"2 \n\t" /* d */\
+ MOVQ" "MM"2, "MM"3 \n\t"\
+ "psubw "MM"6, "MM"2 \n\t" /* d-diff */\
+ "paddw "MM"6, "MM"3 \n\t" /* d+diff */\
+ "pmaxsw "MM"2, "MM"1 \n\t"\
+ "pminsw "MM"3, "MM"1 \n\t" /* d = clip(spatial_pred, d-diff, d+diff); */\
+ "packuswb "MM"1, "MM"1 \n\t"\
+\
+ ::[prev] "r"(prev),\
+ [cur] "r"(cur),\
+ [next] "r"(next),\
+ [prefs]"r"((x86_reg)prefs),\
+ [mrefs]"r"((x86_reg)mrefs),\
+ [mode] "g"(mode),\
+ [tmp] "r"(tmp)\
+ );\
+ __asm__ volatile(MOV" "MM"1, %0" :"=m"(*dst));\
+ dst += STEP;\
+ prev+= STEP;\
+ cur += STEP;\
+ next+= STEP;\
+ }
+
+ if (parity) {
+#define prev2 "prev"
+#define next2 "cur"
+ FILTER
+#undef prev2
+#undef next2
+ } else {
+#define prev2 "cur"
+#define next2 "next"
+ FILTER
+#undef prev2
+#undef next2
+ }
+}
+
+#undef STEP
+#undef MM
+#undef MOV
+#undef MOVQ
+#undef MOVQU
+#undef PSHUF
+#undef PSRL1
+#undef PSRL2
+#undef LOAD
+#undef PABS
+#undef CHECK
+#undef CHECK1
+#undef CHECK2
+#undef FILTER