From e79b977fdb2071298af011fd4b9debebc4220a34 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 10 May 2013 17:30:48 -0700 Subject: videofilters: Add videodiff element --- gst/videofilters/Makefile.am | 3 + gst/videofilters/gstvideodiff.c | 292 ++++++++++++++++++++++++++++++++++ gst/videofilters/gstvideodiff.h | 58 +++++++ gst/videofilters/gstvideofiltersbad.c | 3 + 4 files changed, 356 insertions(+) create mode 100644 gst/videofilters/gstvideodiff.c create mode 100644 gst/videofilters/gstvideodiff.h (limited to 'gst/videofilters') 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 + * + * 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. + * + * + * Example launch line + * |[ + * gst-launch -v fakesrc ! videodiff ! FIXME ! fakesink + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#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 "); + + 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 + * + * 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 +#include +#include + +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 #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; } -- cgit v1.2.1