From 83862968a37112202907eb2cff32b42286e8ffda Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 5 Apr 2013 21:31:18 -0700 Subject: [PATCH] videofiltersbad: port to 1.0 --- configure.ac | 2 +- gst/videofilters/Makefile.am | 2 - gst/videofilters/gstscenechange.c | 177 +++++++++---------- gst/videofilters/gstscenechange.h | 11 +- gst/videofilters/gstvideofilter2.c | 269 ----------------------------- gst/videofilters/gstvideofilter2.h | 81 --------- gst/videofilters/gstzebrastripe.c | 248 ++++++++++++++------------ gst/videofilters/gstzebrastripe.h | 7 +- 8 files changed, 231 insertions(+), 566 deletions(-) delete mode 100644 gst/videofilters/gstvideofilter2.c delete mode 100644 gst/videofilters/gstvideofilter2.h diff --git a/configure.ac b/configure.ac index 561bced91a..2c612468e2 100644 --- a/configure.ac +++ b/configure.ac @@ -321,7 +321,7 @@ GST_PLUGINS_NONPORTED=" aiff \ kate librfb \ mve mythtv nsf nuvdemux \ patchdetect real \ - sdi stereo tta videofilters \ + sdi stereo tta \ videomeasure videosignal vmnc \ linsys vcd \ apexsink cdaudio dc1394 dirac directfb \ diff --git a/gst/videofilters/Makefile.am b/gst/videofilters/Makefile.am index 6a142f1c4a..a515dd464d 100644 --- a/gst/videofilters/Makefile.am +++ b/gst/videofilters/Makefile.am @@ -4,8 +4,6 @@ plugin_LTLIBRARIES = libgstvideofiltersbad.la #include $(top_srcdir)/common/orc.mak libgstvideofiltersbad_la_SOURCES = \ - gstvideofilter2.c \ - gstvideofilter2.h \ gstzebrastripe.c \ gstscenechange.c \ gstvideofiltersbad.c diff --git a/gst/videofilters/gstscenechange.c b/gst/videofilters/gstscenechange.c index 864cad3404..cb893197cb 100644 --- a/gst/videofilters/gstscenechange.c +++ b/gst/videofilters/gstscenechange.c @@ -78,11 +78,10 @@ #endif #include -#include #include -#include "gstvideofilter2.h" -#include "gstscenechange.h" +#include #include +#include "gstscenechange.h" GST_DEBUG_CATEGORY_STATIC (gst_scene_change_debug_category); #define GST_CAT_DEFAULT gst_scene_change_debug_category @@ -97,12 +96,11 @@ static void gst_scene_change_get_property (GObject * object, static void gst_scene_change_dispose (GObject * object); static void gst_scene_change_finalize (GObject * object); -static gboolean gst_scene_change_start (GstBaseTransform * trans); -static gboolean gst_scene_change_stop (GstBaseTransform * trans); -static GstFlowReturn -gst_scene_change_prefilter (GstVideoFilter2 * videofilter2, GstBuffer * buf); - -static GstVideoFilter2Functions gst_scene_change_filter_functions[]; +static gboolean gst_scene_change_set_info (GstVideoFilter * filter, + GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps, + GstVideoInfo * out_info); +static GstFlowReturn gst_scene_change_transform_frame_ip (GstVideoFilter * + filter, GstVideoFrame * frame); #undef TESTING #ifdef TESTING @@ -114,54 +112,46 @@ enum PROP_0 }; -/* pad templates */ - +#define VIDEO_CAPS \ + GST_VIDEO_CAPS_MAKE("{ I420, Y42B, Y41B, Y444 }") /* class initialization */ -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_scene_change_debug_category, "scenechange", 0, \ - "debug category for scenechange element"); - -GST_BOILERPLATE_FULL (GstSceneChange, gst_scene_change, GstVideoFilter2, - GST_TYPE_VIDEO_FILTER2, DEBUG_INIT); - -static void -gst_scene_change_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - - gst_element_class_set_static_metadata (element_class, "Scene change detector", - "Video/Filter", "Detects scene changes in video", - "David Schleef "); -} +G_DEFINE_TYPE_WITH_CODE (GstSceneChange, gst_scene_change, + GST_TYPE_VIDEO_FILTER, + GST_DEBUG_CATEGORY_INIT (gst_scene_change_debug_category, "scenechange", 0, + "debug category for scenechange element")); static void gst_scene_change_class_init (GstSceneChangeClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstBaseTransformClass *base_transform_class = - GST_BASE_TRANSFORM_CLASS (klass); - GstVideoFilter2Class *video_filter2_class = GST_VIDEO_FILTER2_CLASS (klass); + GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass); + + 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_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_CAPS))); + + gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass), + "Scene change detector", + "Video/Filter", "Detects scene changes in video", + "David Schleef "); gobject_class->set_property = gst_scene_change_set_property; gobject_class->get_property = gst_scene_change_get_property; gobject_class->dispose = gst_scene_change_dispose; gobject_class->finalize = gst_scene_change_finalize; - base_transform_class->start = GST_DEBUG_FUNCPTR (gst_scene_change_start); - base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_scene_change_stop); - video_filter2_class->prefilter = - GST_DEBUG_FUNCPTR (gst_scene_change_prefilter); - - gst_video_filter2_class_add_functions (video_filter2_class, - gst_scene_change_filter_functions); + video_filter_class->set_info = GST_DEBUG_FUNCPTR (gst_scene_change_set_info); + video_filter_class->transform_frame_ip = + GST_DEBUG_FUNCPTR (gst_scene_change_transform_frame_ip); } static void -gst_scene_change_init (GstSceneChange * scenechange, - GstSceneChangeClass * scenechange_class) +gst_scene_change_init (GstSceneChange * scenechange) { } @@ -169,7 +159,9 @@ void gst_scene_change_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { - g_return_if_fail (GST_IS_SCENE_CHANGE (object)); + GstSceneChange *scenechange = GST_SCENE_CHANGE (object); + + GST_DEBUG_OBJECT (scenechange, "set_property"); switch (property_id) { default: @@ -182,7 +174,9 @@ void gst_scene_change_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { - g_return_if_fail (GST_IS_SCENE_CHANGE (object)); + GstSceneChange *scenechange = GST_SCENE_CHANGE (object); + + GST_DEBUG_OBJECT (scenechange, "get_property"); switch (property_id) { default: @@ -194,105 +188,107 @@ gst_scene_change_get_property (GObject * object, guint property_id, void gst_scene_change_dispose (GObject * object) { - g_return_if_fail (GST_IS_SCENE_CHANGE (object)); + GstSceneChange *scenechange = GST_SCENE_CHANGE (object); + + GST_DEBUG_OBJECT (scenechange, "dispose"); /* clean up as possible. may be called multiple times */ - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (gst_scene_change_parent_class)->dispose (object); } void gst_scene_change_finalize (GObject * object) { - GstSceneChange *scenechange; + GstSceneChange *scenechange = GST_SCENE_CHANGE (object); - g_return_if_fail (GST_IS_SCENE_CHANGE (object)); - scenechange = GST_SCENE_CHANGE (object); + GST_DEBUG_OBJECT (scenechange, "finalize"); - if (scenechange->oldbuf) - gst_buffer_unref (scenechange->oldbuf); + /* clean up object here */ - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_scene_change_parent_class)->finalize (object); } - static gboolean -gst_scene_change_start (GstBaseTransform * trans) +gst_scene_change_set_info (GstVideoFilter * filter, GstCaps * incaps, + GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info) { + GstSceneChange *scenechange = GST_SCENE_CHANGE (filter); + + GST_DEBUG_OBJECT (scenechange, "set_info"); return TRUE; } -static gboolean -gst_scene_change_stop (GstBaseTransform * trans) -{ - - return TRUE; -} - -static GstFlowReturn -gst_scene_change_prefilter (GstVideoFilter2 * video_filter2, GstBuffer * buf) -{ - - return GST_FLOW_OK; -} static double -get_frame_score (guint8 * s1, guint8 * s2, int width, int height) +get_frame_score (GstVideoFrame * f1, GstVideoFrame * f2) { int i; int j; int score = 0; + int width, height; + guint8 *s1; + guint8 *s2; + + width = f1->info.width; + height = f1->info.height; for (j = 0; j < height; j++) { + s1 = (guint8 *) f1->data[0] + f1->info.stride[0] * j; + s2 = (guint8 *) f2->data[0] + f2->info.stride[0] * j; for (i = 0; i < width; i++) { score += ABS (s1[i] - s2[i]); } - s1 += width; - s2 += width; } return ((double) score) / (width * height); } static GstFlowReturn -gst_scene_change_filter_ip_I420 (GstVideoFilter2 * videofilter2, - GstBuffer * buf, int start, int end) +gst_scene_change_transform_frame_ip (GstVideoFilter * filter, + GstVideoFrame * frame) { - GstSceneChange *scenechange; + GstSceneChange *scenechange = GST_SCENE_CHANGE (filter); + GstVideoFrame oldframe; double score_min; double score_max; double threshold; double score; gboolean change; + gboolean ret; int i; - int width; - int height; - g_return_val_if_fail (GST_IS_SCENE_CHANGE (videofilter2), GST_FLOW_ERROR); - scenechange = GST_SCENE_CHANGE (videofilter2); - - width = GST_VIDEO_FILTER2_WIDTH (videofilter2); - height = GST_VIDEO_FILTER2_HEIGHT (videofilter2); + GST_DEBUG_OBJECT (scenechange, "transform_frame_ip"); if (!scenechange->oldbuf) { scenechange->n_diffs = 0; memset (scenechange->diffs, 0, sizeof (double) * SC_N_DIFFS); - scenechange->oldbuf = gst_buffer_ref (buf); + scenechange->oldbuf = gst_buffer_ref (frame->buffer); return GST_FLOW_OK; } - score = get_frame_score (GST_BUFFER_DATA (scenechange->oldbuf), - GST_BUFFER_DATA (buf), width, height); + ret = + gst_video_frame_map (&oldframe, &scenechange->oldinfo, + scenechange->oldbuf, GST_MAP_READ); + if (!ret) { + GST_ERROR_OBJECT (scenechange, "failed to map old video frame"); + return GST_FLOW_ERROR; + } + + score = get_frame_score (&oldframe, frame); + + gst_video_frame_unmap (&oldframe); + + gst_buffer_unref (scenechange->oldbuf); + scenechange->oldbuf = gst_buffer_ref (frame->buffer); + memcpy (&scenechange->oldinfo, &frame->info, sizeof (GstVideoInfo)); memmove (scenechange->diffs, scenechange->diffs + 1, sizeof (double) * (SC_N_DIFFS - 1)); scenechange->diffs[SC_N_DIFFS - 1] = score; scenechange->n_diffs++; - gst_buffer_unref (scenechange->oldbuf); - scenechange->oldbuf = gst_buffer_ref (buf); - score_min = scenechange->diffs[0]; score_max = scenechange->diffs[0]; for (i = 1; i < SC_N_DIFFS - 1; i++) { @@ -328,11 +324,13 @@ gst_scene_change_filter_ip_I420 (GstVideoFilter2 * videofilter2, if (change) { GstEvent *event; - GST_DEBUG_OBJECT (scenechange, "%d %g %g %g %d", + GST_INFO_OBJECT (scenechange, "%d %g %g %g %d", scenechange->n_diffs, score / threshold, score, threshold, change); - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, - gst_structure_new ("GstForceKeyUnit", NULL)); + event = + gst_video_event_new_downstream_force_key_unit (GST_BUFFER_PTS + (frame->buffer), GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, FALSE, + scenechange->count++); gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (scenechange), event); } @@ -340,11 +338,6 @@ gst_scene_change_filter_ip_I420 (GstVideoFilter2 * videofilter2, return GST_FLOW_OK; } -static GstVideoFilter2Functions gst_scene_change_filter_functions[] = { - {GST_VIDEO_FORMAT_I420, NULL, gst_scene_change_filter_ip_I420}, - {GST_VIDEO_FORMAT_UNKNOWN} -}; - diff --git a/gst/videofilters/gstscenechange.h b/gst/videofilters/gstscenechange.h index c14cc4b495..762c5a8bae 100644 --- a/gst/videofilters/gstscenechange.h +++ b/gst/videofilters/gstscenechange.h @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) 2011 FIXME + * Copyright (C) 2011 David Schleef * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,9 +20,8 @@ #ifndef _GST_SCENE_CHANGE_H_ #define _GST_SCENE_CHANGE_H_ -#include #include -#include "gstvideofilter2.h" +#include G_BEGIN_DECLS @@ -39,16 +38,18 @@ typedef struct _GstSceneChangeClass GstSceneChangeClass; struct _GstSceneChange { - GstVideoFilter2 base_scenechange; + GstVideoFilter base_scenechange; int n_diffs; double diffs[SC_N_DIFFS]; GstBuffer *oldbuf; + GstVideoInfo oldinfo; + int count; }; struct _GstSceneChangeClass { - GstVideoFilter2Class base_scenechange_class; + GstVideoFilterClass base_scenechange_class; }; GType gst_scene_change_get_type (void); diff --git a/gst/videofilters/gstvideofilter2.c b/gst/videofilters/gstvideofilter2.c deleted file mode 100644 index adcdbd23a3..0000000000 --- a/gst/videofilters/gstvideofilter2.c +++ /dev/null @@ -1,269 +0,0 @@ -/* GStreamer - * Copyright (C) 2011 David Schleef - * - * 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-gstvideofilter2 - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include "gstvideofilter2.h" - -GST_DEBUG_CATEGORY_STATIC (gst_video_filter2_debug_category); -#define GST_CAT_DEFAULT gst_video_filter2_debug_category - -/* prototypes */ - - -static void gst_video_filter2_set_property (GObject * object, - guint property_id, const GValue * value, GParamSpec * pspec); -static void gst_video_filter2_get_property (GObject * object, - guint property_id, GValue * value, GParamSpec * pspec); -static void gst_video_filter2_dispose (GObject * object); -static void gst_video_filter2_finalize (GObject * object); - -static GstCaps *gst_video_filter2_transform_caps (GstBaseTransform * trans, - GstPadDirection direction, GstCaps * caps); -static gboolean -gst_video_filter2_get_unit_size (GstBaseTransform * trans, GstCaps * caps, - guint * size); -static gboolean -gst_video_filter2_set_caps (GstBaseTransform * trans, GstCaps * incaps, - GstCaps * outcaps); -static gboolean gst_video_filter2_start (GstBaseTransform * trans); -static gboolean gst_video_filter2_stop (GstBaseTransform * trans); -static GstFlowReturn gst_video_filter2_transform (GstBaseTransform * trans, - GstBuffer * inbuf, GstBuffer * outbuf); -static GstFlowReturn gst_video_filter2_transform_ip (GstBaseTransform * trans, - GstBuffer * buf); - -enum -{ - PROP_0 -}; - - -/* class initialization */ - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_video_filter2_debug_category, "videofilter2", 0, \ - "debug category for videofilter2 element"); - -GST_BOILERPLATE_FULL (GstVideoFilter2, gst_video_filter2, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); - -static void -gst_video_filter2_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - int i; - GstCaps *caps = NULL; - - caps = gst_caps_new_empty (); - for (i = GST_VIDEO_FORMAT_I420; i <= GST_VIDEO_FORMAT_I420; i++) { - gst_caps_append (caps, gst_video_format_new_template_caps (i)); - } - - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - gst_caps_ref (caps))); - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps)); -} - -static void -gst_video_filter2_class_init (GstVideoFilter2Class * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstBaseTransformClass *base_transform_class = - GST_BASE_TRANSFORM_CLASS (klass); - - gobject_class->set_property = gst_video_filter2_set_property; - gobject_class->get_property = gst_video_filter2_get_property; - gobject_class->dispose = gst_video_filter2_dispose; - gobject_class->finalize = gst_video_filter2_finalize; - base_transform_class->transform_caps = - GST_DEBUG_FUNCPTR (gst_video_filter2_transform_caps); - base_transform_class->get_unit_size = - GST_DEBUG_FUNCPTR (gst_video_filter2_get_unit_size); - base_transform_class->set_caps = - GST_DEBUG_FUNCPTR (gst_video_filter2_set_caps); - base_transform_class->start = GST_DEBUG_FUNCPTR (gst_video_filter2_start); - base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_video_filter2_stop); - base_transform_class->transform = - GST_DEBUG_FUNCPTR (gst_video_filter2_transform); - base_transform_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_video_filter2_transform_ip); - -} - -static void -gst_video_filter2_init (GstVideoFilter2 * videofilter2, - GstVideoFilter2Class * videofilter2_class) -{ - - gst_base_transform_set_qos_enabled (GST_BASE_TRANSFORM (videofilter2), TRUE); -} - -void -gst_video_filter2_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - g_return_if_fail (GST_IS_VIDEO_FILTER2 (object)); - - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_video_filter2_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - g_return_if_fail (GST_IS_VIDEO_FILTER2 (object)); - - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_video_filter2_dispose (GObject * object) -{ - g_return_if_fail (GST_IS_VIDEO_FILTER2 (object)); - - /* clean up as possible. may be called multiple times */ - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -void -gst_video_filter2_finalize (GObject * object) -{ - g_return_if_fail (GST_IS_VIDEO_FILTER2 (object)); - - /* clean up object here */ - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static GstCaps * -gst_video_filter2_transform_caps (GstBaseTransform * trans, - GstPadDirection direction, GstCaps * caps) -{ - return gst_caps_ref (caps); -} - -static gboolean -gst_video_filter2_get_unit_size (GstBaseTransform * trans, GstCaps * caps, - guint * size) -{ - GstVideoFormat format; - gint width, height; - gboolean ret; - - ret = gst_video_format_parse_caps (caps, &format, &width, &height); - *size = gst_video_format_get_size (format, width, height); - - return ret; -} - -static gboolean -gst_video_filter2_set_caps (GstBaseTransform * trans, GstCaps * incaps, - GstCaps * outcaps) -{ - GstVideoFilter2 *videofilter2; - gboolean ret; - int width; - int height; - GstVideoFormat format; - - g_return_val_if_fail (GST_IS_VIDEO_FILTER2 (trans), FALSE); - videofilter2 = GST_VIDEO_FILTER2 (trans); - - ret = gst_video_format_parse_caps (incaps, &format, &width, &height); - - if (ret) { - videofilter2->format = format; - videofilter2->width = width; - videofilter2->height = height; - } - - return ret; -} - -static gboolean -gst_video_filter2_start (GstBaseTransform * trans) -{ - - return FALSE; -} - -static gboolean -gst_video_filter2_stop (GstBaseTransform * trans) -{ - - return FALSE; -} - -static GstFlowReturn -gst_video_filter2_transform (GstBaseTransform * trans, GstBuffer * inbuf, - GstBuffer * outbuf) -{ - - return GST_FLOW_ERROR; -} - -static GstFlowReturn -gst_video_filter2_transform_ip (GstBaseTransform * trans, GstBuffer * buf) -{ - GstVideoFilter2 *video_filter2 = GST_VIDEO_FILTER2 (trans); - GstVideoFilter2Class *klass = - GST_VIDEO_FILTER2_CLASS (G_OBJECT_GET_CLASS (trans)); - int i; - GstFlowReturn ret; - - for (i = 0; klass->functions[i].format != GST_VIDEO_FORMAT_UNKNOWN; i++) { - if (klass->functions[i].format == video_filter2->format) { - ret = klass->functions[i].filter_ip (video_filter2, buf, 0, - video_filter2->height); - return ret; - } - } - - return GST_FLOW_ERROR; -} - -/* API */ - -void -gst_video_filter2_class_add_functions (GstVideoFilter2Class * klass, - const GstVideoFilter2Functions * functions) -{ - klass->functions = functions; -} diff --git a/gst/videofilters/gstvideofilter2.h b/gst/videofilters/gstvideofilter2.h deleted file mode 100644 index 4916dbd7e2..0000000000 --- a/gst/videofilters/gstvideofilter2.h +++ /dev/null @@ -1,81 +0,0 @@ -/* GStreamer - * Copyright (C) 2011 David Schleef - * - * 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_FILTER2_H_ -#define _GST_VIDEO_FILTER2_H_ - -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_VIDEO_FILTER2 (gst_video_filter2_get_type()) -#define GST_VIDEO_FILTER2(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_FILTER2,GstVideoFilter2)) -#define GST_VIDEO_FILTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_FILTER2,GstVideoFilter2Class)) -#define GST_IS_VIDEO_FILTER2(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_FILTER2)) -#define GST_IS_VIDEO_FILTER2_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_FILTER2)) - -typedef struct _GstVideoFilter2 GstVideoFilter2; -typedef struct _GstVideoFilter2Class GstVideoFilter2Class; -typedef struct _GstVideoFilter2Functions GstVideoFilter2Functions; - -struct _GstVideoFilter2 -{ - GstBaseTransform base_videofilter2; - - GstVideoFormat format; - int width; - int height; - - gpointer _gst_reserved[GST_PADDING_LARGE]; -}; - -struct _GstVideoFilter2Class -{ - GstBaseTransformClass base_videofilter2_class; - - const GstVideoFilter2Functions *functions; - - GstFlowReturn (*prefilter) (GstVideoFilter2 *filter, GstBuffer *inbuf); - - gpointer _gst_reserved[GST_PADDING_LARGE]; -}; - -struct _GstVideoFilter2Functions -{ - GstVideoFormat format; - GstFlowReturn (*filter) (GstVideoFilter2 *filter, GstBuffer *inbuf, - GstBuffer *outbuf, int start, int end); - GstFlowReturn (*filter_ip) (GstVideoFilter2 *filter, GstBuffer *buffer, - int start, int end); - gpointer _gst_reserved[GST_PADDING_LARGE]; -}; - -#define GST_VIDEO_FILTER2_FORMAT(vf) (((GstVideoFilter2 *)vf)->format) -#define GST_VIDEO_FILTER2_WIDTH(vf) (((GstVideoFilter2 *)vf)->width) -#define GST_VIDEO_FILTER2_HEIGHT(vf) (((GstVideoFilter2 *)vf)->height) - -GType gst_video_filter2_get_type (void); - -void gst_video_filter2_class_add_functions (GstVideoFilter2Class *klass, - const GstVideoFilter2Functions *functions); - -G_END_DECLS - -#endif diff --git a/gst/videofilters/gstzebrastripe.c b/gst/videofilters/gstzebrastripe.c index 62306887ab..d512548ed4 100644 --- a/gst/videofilters/gstzebrastripe.c +++ b/gst/videofilters/gstzebrastripe.c @@ -47,10 +47,10 @@ #endif #include -#include #include -#include +#include #include "gstzebrastripe.h" +#include GST_DEBUG_CATEGORY_STATIC (gst_zebra_stripe_debug_category); #define GST_CAT_DEFAULT gst_zebra_stripe_debug_category @@ -62,15 +62,16 @@ static void gst_zebra_stripe_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); static void gst_zebra_stripe_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); +static void gst_zebra_stripe_dispose (GObject * object); static void gst_zebra_stripe_finalize (GObject * object); - static gboolean gst_zebra_stripe_start (GstBaseTransform * trans); static gboolean gst_zebra_stripe_stop (GstBaseTransform * trans); -static GstFlowReturn -gst_zebra_stripe_prefilter (GstVideoFilter2 * videofilter2, GstBuffer * buf); - -static GstVideoFilter2Functions gst_zebra_stripe_filter_functions[]; +static gboolean gst_zebra_stripe_set_info (GstVideoFilter * filter, + GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps, + GstVideoInfo * out_info); +static GstFlowReturn gst_zebra_stripe_transform_frame_ip (GstVideoFilter * + filter, GstVideoFrame * frame); enum { @@ -80,68 +81,71 @@ enum #define DEFAULT_THRESHOLD 90 +/* pad templates */ + +#define VIDEO_CAPS GST_VIDEO_CAPS_MAKE( \ + "{ I420, Y444, Y42B, Y41B, YUY2, UYVY, AYUV }") + + /* class initialization */ -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_zebra_stripe_debug_category, "zebrastripe", 0, \ - "debug category for zebrastripe element"); - -GST_BOILERPLATE_FULL (GstZebraStripe, gst_zebra_stripe, GstVideoFilter2, - GST_TYPE_VIDEO_FILTER2, DEBUG_INIT); - -static void -gst_zebra_stripe_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_static_metadata (element_class, "Zebra stripe overlay", - "Filter/Analysis", - "Overlays zebra striping on overexposed areas of video", - "David Schleef "); -} +G_DEFINE_TYPE_WITH_CODE (GstZebraStripe, gst_zebra_stripe, + GST_TYPE_VIDEO_FILTER, + GST_DEBUG_CATEGORY_INIT (gst_zebra_stripe_debug_category, "zebrastripe", 0, + "debug category for zebrastripe element")); static void gst_zebra_stripe_class_init (GstZebraStripeClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstVideoFilter2Class *video_filter2_class = GST_VIDEO_FILTER2_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_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_CAPS))); + + gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass), + "Zebra stripe overlay", + "Filter/Analysis", + "Overlays zebra striping on overexposed areas of video", + "David Schleef "); gobject_class->set_property = gst_zebra_stripe_set_property; gobject_class->get_property = gst_zebra_stripe_get_property; + gobject_class->dispose = gst_zebra_stripe_dispose; gobject_class->finalize = gst_zebra_stripe_finalize; base_transform_class->start = GST_DEBUG_FUNCPTR (gst_zebra_stripe_start); base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_zebra_stripe_stop); - - video_filter2_class->prefilter = - GST_DEBUG_FUNCPTR (gst_zebra_stripe_prefilter); + video_filter_class->set_info = GST_DEBUG_FUNCPTR (gst_zebra_stripe_set_info); + video_filter_class->transform_frame_ip = + GST_DEBUG_FUNCPTR (gst_zebra_stripe_transform_frame_ip); g_object_class_install_property (gobject_class, PROP_THRESHOLD, g_param_spec_int ("threshold", "Threshold", "Threshold above which the video is striped", 0, 100, DEFAULT_THRESHOLD, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - - gst_video_filter2_class_add_functions (video_filter2_class, - gst_zebra_stripe_filter_functions); } static void -gst_zebra_stripe_init (GstZebraStripe * zebrastripe, - GstZebraStripeClass * zebrastripe_class) +gst_zebra_stripe_init (GstZebraStripe * zebrastripe) { - } void gst_zebra_stripe_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { - GstZebraStripe *zebrastripe; + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (object); - g_return_if_fail (GST_IS_ZEBRA_STRIPE (object)); - zebrastripe = GST_ZEBRA_STRIPE (object); + GST_DEBUG_OBJECT (zebrastripe, "set_property"); switch (property_id) { case PROP_THRESHOLD: @@ -159,10 +163,9 @@ void gst_zebra_stripe_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { - GstZebraStripe *zebrastripe; + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (object); - g_return_if_fail (GST_IS_ZEBRA_STRIPE (object)); - zebrastripe = GST_ZEBRA_STRIPE (object); + GST_DEBUG_OBJECT (zebrastripe, "get_property"); switch (property_id) { case PROP_THRESHOLD: @@ -174,60 +177,79 @@ gst_zebra_stripe_get_property (GObject * object, guint property_id, } } +void +gst_zebra_stripe_dispose (GObject * object) +{ + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (object); + + GST_DEBUG_OBJECT (zebrastripe, "dispose"); + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (gst_zebra_stripe_parent_class)->dispose (object); +} + void gst_zebra_stripe_finalize (GObject * object) { - g_return_if_fail (GST_IS_ZEBRA_STRIPE (object)); + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (object); + + GST_DEBUG_OBJECT (zebrastripe, "finalize"); /* clean up object here */ - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_zebra_stripe_parent_class)->finalize (object); } - static gboolean gst_zebra_stripe_start (GstBaseTransform * trans) { + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (trans); + GST_DEBUG_OBJECT (zebrastripe, "start"); + + if (GST_BASE_TRANSFORM_CLASS (gst_zebra_stripe_parent_class)->start) + return + GST_BASE_TRANSFORM_CLASS (gst_zebra_stripe_parent_class)->start (trans); return TRUE; } static gboolean gst_zebra_stripe_stop (GstBaseTransform * trans) { + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (trans); + + GST_DEBUG_OBJECT (zebrastripe, "stop"); + + if (GST_BASE_TRANSFORM_CLASS (gst_zebra_stripe_parent_class)->stop) + return + GST_BASE_TRANSFORM_CLASS (gst_zebra_stripe_parent_class)->stop (trans); + return TRUE; +} + +static gboolean +gst_zebra_stripe_set_info (GstVideoFilter * filter, GstCaps * incaps, + GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info) +{ + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (filter); + + GST_DEBUG_OBJECT (zebrastripe, "set_info"); return TRUE; } static GstFlowReturn -gst_zebra_stripe_prefilter (GstVideoFilter2 * videofilter2, GstBuffer * buf) +gst_zebra_stripe_transform_frame_ip_planarY (GstZebraStripe * zebrastripe, + GstVideoFrame * frame) { - GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (videofilter2); - - zebrastripe->t++; - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_zebra_stripe_filter_ip_planarY (GstVideoFilter2 * videofilter2, - GstBuffer * buf, int start, int end) -{ - GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (videofilter2); - int width = GST_VIDEO_FILTER2_WIDTH (zebrastripe); + int width = frame->info.width; + int height = frame->info.height; int i, j; int threshold = zebrastripe->y_threshold; int t = zebrastripe->t; - guint8 *ydata; - int ystride; - ydata = GST_BUFFER_DATA (buf); - ystride = - gst_video_format_get_row_stride (GST_VIDEO_FILTER2_FORMAT (videofilter2), - 0, width); - - for (j = start; j < end; j++) { - guint8 *data = ydata + ystride * j; + for (j = 0; j < height; j++) { + guint8 *data = (guint8 *) frame->data[0] + frame->info.stride[0] * j; for (i = 0; i < width; i++) { if (data[i] >= threshold) { if ((i + j + t) & 0x4) @@ -239,27 +261,23 @@ gst_zebra_stripe_filter_ip_planarY (GstVideoFilter2 * videofilter2, } static GstFlowReturn -gst_zebra_stripe_filter_ip_YxYy (GstVideoFilter2 * videofilter2, - GstBuffer * buf, int start, int end) +gst_zebra_stripe_transform_frame_ip_YUY2 (GstZebraStripe * zebrastripe, + GstVideoFrame * frame) { - GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (videofilter2); - GstVideoFormat format = GST_VIDEO_FILTER2_FORMAT (zebrastripe); - int width = GST_VIDEO_FILTER2_WIDTH (zebrastripe); + int width = frame->info.width; + int height = frame->info.height; int i, j; int threshold = zebrastripe->y_threshold; int t = zebrastripe->t; - guint8 *ydata; - int ystride; + int offset = 0; - ydata = GST_BUFFER_DATA (buf); - ystride = gst_video_format_get_row_stride (format, 0, width); - - if (format == GST_VIDEO_FORMAT_UYVY) { - ydata++; + if (frame->info.finfo->format == GST_VIDEO_FORMAT_UYVY) { + offset = 1; } - for (j = start; j < end; j++) { - guint8 *data = ydata + ystride * j; + for (j = 0; j < height; j++) { + guint8 *data = + (guint8 *) frame->data[0] + frame->info.stride[0] * j + offset; for (i = 0; i < width; i++) { if (data[2 * i] >= threshold) { if ((i + j + t) & 0x4) @@ -271,29 +289,21 @@ gst_zebra_stripe_filter_ip_YxYy (GstVideoFilter2 * videofilter2, } static GstFlowReturn -gst_zebra_stripe_filter_ip_AYUV (GstVideoFilter2 * videofilter2, - GstBuffer * buf, int start, int end) +gst_zebra_stripe_transform_frame_ip_AYUV (GstZebraStripe * zebrastripe, + GstVideoFrame * frame) { - GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (videofilter2); - int width = GST_VIDEO_FILTER2_WIDTH (zebrastripe); + int width = frame->info.width; + int height = frame->info.height; int i, j; int threshold = zebrastripe->y_threshold; int t = zebrastripe->t; - guint8 *ydata; - int ystride; - ydata = GST_BUFFER_DATA (buf); - ystride = - gst_video_format_get_row_stride (GST_VIDEO_FILTER2_FORMAT (videofilter2), - 0, width); - - ydata++; - for (j = start; j < end; j++) { - guint8 *data = ydata + ystride * j; + for (j = 0; j < height; j++) { + guint8 *data = (guint8 *) frame->data[0] + frame->info.stride[0] * j; for (i = 0; i < width; i++) { - if (data[4 * i] >= threshold) { + if (data[4 * i + 1] >= threshold) { if ((i + j + t) & 0x4) - data[4 * i] = 16; + data[4 * i + 1] = 16; } } } @@ -301,19 +311,33 @@ gst_zebra_stripe_filter_ip_AYUV (GstVideoFilter2 * videofilter2, return GST_FLOW_OK; } -static GstVideoFilter2Functions gst_zebra_stripe_filter_functions[] = { - {GST_VIDEO_FORMAT_I420, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_YV12, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_Y41B, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_Y42B, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_NV12, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_NV21, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_YUV9, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_YVU9, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_Y444, NULL, gst_zebra_stripe_filter_ip_planarY}, - {GST_VIDEO_FORMAT_UYVY, NULL, gst_zebra_stripe_filter_ip_YxYy}, - {GST_VIDEO_FORMAT_YUY2, NULL, gst_zebra_stripe_filter_ip_YxYy}, - {GST_VIDEO_FORMAT_YVYU, NULL, gst_zebra_stripe_filter_ip_YxYy}, - {GST_VIDEO_FORMAT_AYUV, NULL, gst_zebra_stripe_filter_ip_AYUV}, - {GST_VIDEO_FORMAT_UNKNOWN} -}; +static GstFlowReturn +gst_zebra_stripe_transform_frame_ip (GstVideoFilter * filter, + GstVideoFrame * frame) +{ + GstZebraStripe *zebrastripe = GST_ZEBRA_STRIPE (filter); + + GST_DEBUG_OBJECT (zebrastripe, "transform_frame_ip"); + zebrastripe->t++; + + switch (frame->info.finfo->format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y42B: + gst_zebra_stripe_transform_frame_ip_planarY (zebrastripe, frame); + break; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + gst_zebra_stripe_transform_frame_ip_YUY2 (zebrastripe, frame); + break; + case GST_VIDEO_FORMAT_AYUV: + gst_zebra_stripe_transform_frame_ip_AYUV (zebrastripe, frame); + break; + default: + g_assert_not_reached (); + } + + + return GST_FLOW_OK; +} diff --git a/gst/videofilters/gstzebrastripe.h b/gst/videofilters/gstzebrastripe.h index 420e045958..479ce5c07f 100644 --- a/gst/videofilters/gstzebrastripe.h +++ b/gst/videofilters/gstzebrastripe.h @@ -20,8 +20,8 @@ #ifndef _GST_ZEBRA_STRIPE_H_ #define _GST_ZEBRA_STRIPE_H_ -#include "gstvideofilter2.h" #include +#include G_BEGIN_DECLS @@ -36,7 +36,7 @@ typedef struct _GstZebraStripeClass GstZebraStripeClass; struct _GstZebraStripe { - GstVideoFilter2 video_filter2; + GstVideoFilter base_zebrastripe; /* properties */ int threshold; @@ -44,12 +44,11 @@ struct _GstZebraStripe /* state */ int t; int y_threshold; - }; struct _GstZebraStripeClass { - GstVideoFilter2Class video_filter2_class; + GstVideoFilterClass base_zebrastripe_class; }; GType gst_zebra_stripe_get_type (void);