summaryrefslogtreecommitdiff
path: root/gst/videofilters
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2013-05-10 17:30:48 -0700
committerDavid Schleef <ds@schleef.org>2013-05-10 17:40:17 -0700
commite79b977fdb2071298af011fd4b9debebc4220a34 (patch)
treed6200f533d11543f9877f6f9f4e6ad677674fa6a /gst/videofilters
parent4b7f0d99f02731793116e35c3b37ff722c949848 (diff)
downloadgstreamer-plugins-bad-e79b977fdb2071298af011fd4b9debebc4220a34.tar.gz
videofilters: Add videodiff element
Diffstat (limited to 'gst/videofilters')
-rw-r--r--gst/videofilters/Makefile.am3
-rw-r--r--gst/videofilters/gstvideodiff.c292
-rw-r--r--gst/videofilters/gstvideodiff.h58
-rw-r--r--gst/videofilters/gstvideofiltersbad.c3
4 files changed, 356 insertions, 0 deletions
diff --git a/gst/videofilters/Makefile.am b/gst/videofilters/Makefile.am
index f2611861d..276f85350 100644
--- a/gst/videofilters/Makefile.am
+++ b/gst/videofilters/Makefile.am
@@ -5,7 +5,10 @@ plugin_LTLIBRARIES = libgstvideofiltersbad.la
libgstvideofiltersbad_la_SOURCES = \
gstzebrastripe.c \
+ gstzebrastripe.h \
gstscenechange.c \
+ gstvideodiff.c \
+ gstvideodiff.h \
gstvideofiltersbad.c
#nodist_libgstvideofiltersbad_la_SOURCES = $(ORC_NODIST_SOURCES)
libgstvideofiltersbad_la_CFLAGS = \
diff --git a/gst/videofilters/gstvideodiff.c b/gst/videofilters/gstvideodiff.c
new file mode 100644
index 000000000..364fa1c46
--- /dev/null
+++ b/gst/videofilters/gstvideodiff.c
@@ -0,0 +1,292 @@
+/* GStreamer
+ * Copyright (C) 2013 FIXME <fixme@example.com>
+ *
+ * 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 Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+/**
+ * SECTION:element-gstvideodiff
+ *
+ * The videodiff element does FIXME stuff.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v fakesrc ! videodiff ! FIXME ! fakesink
+ * ]|
+ * FIXME Describe what the pipeline does.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideofilter.h>
+#include "gstvideodiff.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_video_diff_debug_category);
+#define GST_CAT_DEFAULT gst_video_diff_debug_category
+
+/* prototypes */
+
+
+static void gst_video_diff_set_property (GObject * object,
+ guint property_id, const GValue * value, GParamSpec * pspec);
+static void gst_video_diff_get_property (GObject * object,
+ guint property_id, GValue * value, GParamSpec * pspec);
+static void gst_video_diff_dispose (GObject * object);
+static void gst_video_diff_finalize (GObject * object);
+
+static gboolean gst_video_diff_start (GstBaseTransform * trans);
+static gboolean gst_video_diff_stop (GstBaseTransform * trans);
+static gboolean gst_video_diff_set_info (GstVideoFilter * filter,
+ GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
+ GstVideoInfo * out_info);
+static GstFlowReturn gst_video_diff_transform_frame (GstVideoFilter * filter,
+ GstVideoFrame * inframe, GstVideoFrame * outframe);
+
+enum
+{
+ PROP_0
+};
+
+/* pad templates */
+
+/* FIXME: add/remove formats you can handle */
+#define VIDEO_SRC_CAPS \
+ GST_VIDEO_CAPS_MAKE("{ I420, Y444, Y42B, UYVY, RGBA }")
+
+/* FIXME: add/remove formats you can handle */
+#define VIDEO_SINK_CAPS \
+ GST_VIDEO_CAPS_MAKE("{ I420, Y444, Y42B, UYVY, RGBA }")
+
+
+/* class initialization */
+
+G_DEFINE_TYPE_WITH_CODE (GstVideoDiff, gst_video_diff, GST_TYPE_VIDEO_FILTER,
+ GST_DEBUG_CATEGORY_INIT (gst_video_diff_debug_category, "videodiff", 0,
+ "debug category for videodiff element"));
+
+static void
+gst_video_diff_class_init (GstVideoDiffClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseTransformClass *base_transform_class =
+ GST_BASE_TRANSFORM_CLASS (klass);
+ GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_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_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ gst_caps_from_string (VIDEO_SRC_CAPS)));
+ gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
+ gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ gst_caps_from_string (VIDEO_SINK_CAPS)));
+
+ gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
+ "FIXME Long name", "Generic", "FIXME Description",
+ "FIXME <fixme@example.com>");
+
+ gobject_class->set_property = gst_video_diff_set_property;
+ gobject_class->get_property = gst_video_diff_get_property;
+ gobject_class->dispose = gst_video_diff_dispose;
+ gobject_class->finalize = gst_video_diff_finalize;
+ base_transform_class->start = GST_DEBUG_FUNCPTR (gst_video_diff_start);
+ base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_video_diff_stop);
+ video_filter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_diff_set_info);
+ video_filter_class->transform_frame =
+ GST_DEBUG_FUNCPTR (gst_video_diff_transform_frame);
+
+}
+
+static void
+gst_video_diff_init (GstVideoDiff * videodiff)
+{
+ videodiff->threshold = 10;
+}
+
+void
+gst_video_diff_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (object);
+
+ GST_DEBUG_OBJECT (videodiff, "set_property");
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_video_diff_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (object);
+
+ GST_DEBUG_OBJECT (videodiff, "get_property");
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_video_diff_dispose (GObject * object)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (object);
+
+ GST_DEBUG_OBJECT (videodiff, "dispose");
+
+ /* clean up as possible. may be called multiple times */
+
+ G_OBJECT_CLASS (gst_video_diff_parent_class)->dispose (object);
+}
+
+void
+gst_video_diff_finalize (GObject * object)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (object);
+
+ GST_DEBUG_OBJECT (videodiff, "finalize");
+
+ /* clean up object here */
+
+ G_OBJECT_CLASS (gst_video_diff_parent_class)->finalize (object);
+}
+
+static gboolean
+gst_video_diff_start (GstBaseTransform * trans)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (trans);
+
+ GST_DEBUG_OBJECT (videodiff, "start");
+
+ return TRUE;
+}
+
+static gboolean
+gst_video_diff_stop (GstBaseTransform * trans)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (trans);
+
+ GST_DEBUG_OBJECT (videodiff, "stop");
+
+ return TRUE;
+}
+
+static gboolean
+gst_video_diff_set_info (GstVideoFilter * filter, GstCaps * incaps,
+ GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (filter);
+
+ GST_DEBUG_OBJECT (videodiff, "set_info");
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_video_diff_transform_frame_ip_planarY (GstVideoDiff * videodiff,
+ GstVideoFrame * outframe, GstVideoFrame * inframe, GstVideoFrame * oldframe)
+{
+ int width = inframe->info.width;
+ int height = inframe->info.height;
+ int i, j;
+ int threshold = videodiff->threshold;
+ int t = videodiff->t;
+
+ for (j = 0; j < height; j++) {
+ guint8 *d = (guint8 *) outframe->data[0] + outframe->info.stride[0] * j;
+ guint8 *s1 = (guint8 *) oldframe->data[0] + oldframe->info.stride[0] * j;
+ guint8 *s2 = (guint8 *) inframe->data[0] + inframe->info.stride[0] * j;
+ for (i = 0; i < width; i++) {
+ if ((s2[i] < s1[i] - threshold) || (s2[i] > s1[i] + threshold)) {
+ if ((i + j + t) & 0x4) {
+ d[i] = 16;
+ } else {
+ d[i] = 240;
+ }
+ } else {
+ d[i] = s2[i];
+ }
+ }
+ }
+ for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (inframe, 1); j++) {
+ guint8 *d = (guint8 *) outframe->data[1] + outframe->info.stride[1] * j;
+ guint8 *s = (guint8 *) inframe->data[1] + inframe->info.stride[1] * j;
+ memcpy (d, s, GST_VIDEO_FRAME_COMP_WIDTH (inframe, 1));
+ }
+ for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (inframe, 2); j++) {
+ guint8 *d = (guint8 *) outframe->data[2] + outframe->info.stride[2] * j;
+ guint8 *s = (guint8 *) inframe->data[2] + inframe->info.stride[2] * j;
+ memcpy (d, s, GST_VIDEO_FRAME_COMP_WIDTH (inframe, 2));
+ }
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_video_diff_transform_frame (GstVideoFilter * filter,
+ GstVideoFrame * inframe, GstVideoFrame * outframe)
+{
+ GstVideoDiff *videodiff = GST_VIDEO_DIFF (filter);
+
+ GST_DEBUG_OBJECT (videodiff, "transform_frame_ip");
+
+ if (videodiff->previous_buffer) {
+ GstVideoFrame oldframe;
+
+ gst_video_frame_map (&oldframe, &videodiff->oldinfo,
+ videodiff->previous_buffer, GST_MAP_READ);
+
+ switch (inframe->info.finfo->format) {
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_Y41B:
+ case GST_VIDEO_FORMAT_Y444:
+ case GST_VIDEO_FORMAT_Y42B:
+ gst_video_diff_transform_frame_ip_planarY (videodiff, outframe,
+ inframe, &oldframe);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gst_video_frame_unmap (&oldframe);
+ gst_buffer_unref (videodiff->previous_buffer);
+ } else {
+ int k;
+ int j;
+ for (k = 0; k < 3; k++) {
+ for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (inframe, k); j++) {
+ guint8 *d = (guint8 *) outframe->data[k] + outframe->info.stride[k] * j;
+ guint8 *s = (guint8 *) inframe->data[k] + inframe->info.stride[k] * j;
+ memcpy (d, s, GST_VIDEO_FRAME_COMP_WIDTH (inframe, k));
+ }
+ }
+ }
+
+ videodiff->previous_buffer = gst_buffer_ref (inframe->buffer);
+ memcpy (&videodiff->oldinfo, &inframe->info, sizeof (GstVideoInfo));
+
+ return GST_FLOW_OK;
+}
diff --git a/gst/videofilters/gstvideodiff.h b/gst/videofilters/gstvideodiff.h
new file mode 100644
index 000000000..c91844a84
--- /dev/null
+++ b/gst/videofilters/gstvideodiff.h
@@ -0,0 +1,58 @@
+/* GStreamer
+ * Copyright (C) 2013 FIXME <fixme@example.com>
+ *
+ * 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_VIDEO_DIFF_H_
+#define _GST_VIDEO_DIFF_H_
+
+#include <gst/video/video.h>
+#include <gst/video/gstvideofilter.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VIDEO_DIFF (gst_video_diff_get_type())
+#define GST_VIDEO_DIFF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_DIFF,GstVideoDiff))
+#define GST_VIDEO_DIFF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_DIFF,GstVideoDiffClass))
+#define GST_IS_VIDEO_DIFF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_DIFF))
+#define GST_IS_VIDEO_DIFF_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_DIFF))
+
+typedef struct _GstVideoDiff GstVideoDiff;
+typedef struct _GstVideoDiffClass GstVideoDiffClass;
+
+struct _GstVideoDiff
+{
+ GstVideoFilter base_videodiff;
+
+ GstBuffer *previous_buffer;
+ GstVideoInfo oldinfo;
+
+ int threshold;
+ int t;
+};
+
+struct _GstVideoDiffClass
+{
+ GstVideoFilterClass base_videodiff_class;
+};
+
+GType gst_video_diff_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gst/videofilters/gstvideofiltersbad.c b/gst/videofilters/gstvideofiltersbad.c
index b65b4d5d1..1f361e498 100644
--- a/gst/videofilters/gstvideofiltersbad.c
+++ b/gst/videofilters/gstvideofiltersbad.c
@@ -25,6 +25,7 @@
#include <gst/base/gstbasetransform.h>
#include "gstscenechange.h"
#include "gstzebrastripe.h"
+#include "gstvideodiff.h"
static gboolean
@@ -35,6 +36,8 @@ plugin_init (GstPlugin * plugin)
gst_scene_change_get_type ());
gst_element_register (plugin, "zebrastripe", GST_RANK_NONE,
gst_zebra_stripe_get_type ());
+ return gst_element_register (plugin, "videodiff", GST_RANK_NONE,
+ GST_TYPE_VIDEO_DIFF);
return TRUE;
}