diff --git a/gst/videosignal/Makefile.am b/gst/videosignal/Makefile.am index 1b3fd51424..0968b2ed3e 100644 --- a/gst/videosignal/Makefile.am +++ b/gst/videosignal/Makefile.am @@ -1,11 +1,13 @@ plugin_LTLIBRARIES = libgstvideosignal.la -noinst_HEADERS = gstvideoanalyse.h gstvideodetect.h gstvideomark.h - libgstvideosignal_la_SOURCES = gstvideosignal.c \ - gstvideoanalyse.c \ - gstvideodetect.c \ - gstvideomark.c + gstvideoanalyse.c \ + gstvideoanalyse.h + +# gstvideodetect.c \ +# gstvideodetect.h \ +# gstvideomark.c \ +# gstvideomark.h libgstvideosignal_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) @@ -25,4 +27,4 @@ Android.mk: Makefile.am $(BUILT_SOURCES) -ldl \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ - > $@ \ No newline at end of file + > $@ diff --git a/gst/videosignal/gstvideoanalyse.c b/gst/videosignal/gstvideoanalyse.c index e114d2d0bc..47cc03fa5c 100644 --- a/gst/videosignal/gstvideoanalyse.c +++ b/gst/videosignal/gstvideoanalyse.c @@ -13,10 +13,9 @@ * * 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. + * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, + * Boston, MA 02110-1335, USA. */ - /** * SECTION:element-videoanalyse * @@ -84,16 +83,25 @@ #include "config.h" #endif +#include +#include +#include #include "gstvideoanalyse.h" -#include -#include +GST_DEBUG_CATEGORY_STATIC (gst_video_analyse_debug_category); +#define GST_CAT_DEFAULT gst_video_analyse_debug_category -#include +/* prototypes */ -/* GstVideoAnalyse signals and args */ -#define DEFAULT_MESSAGE TRUE +static void gst_video_analyse_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_video_analyse_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_video_analyse_finalize (GObject * object); + +static GstFlowReturn gst_video_analyse_transform_frame_ip (GstVideoFilter * + filter, GstVideoFrame * frame); enum { @@ -101,57 +109,106 @@ enum PROP_MESSAGE }; -GST_DEBUG_CATEGORY_STATIC (video_analyse_debug); -#define GST_CAT_DEFAULT video_analyse_debug +#define DEFAULT_MESSAGE TRUE -static GstStaticPadTemplate gst_video_analyse_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YV12 }")) - ); +#define VIDEO_CAPS \ + GST_VIDEO_CAPS_MAKE("{ I420, YV12, Y444, Y42B, Y41B }") -static GstStaticPadTemplate gst_video_analyse_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YV12 }")) - ); -static GstVideoFilterClass *parent_class = NULL; +/* class initialization */ -static gboolean -gst_video_analyse_set_caps (GstBaseTransform * btrans, GstCaps * incaps, - GstCaps * outcaps) +G_DEFINE_TYPE_WITH_CODE (GstVideoAnalyse, gst_video_analyse, + GST_TYPE_VIDEO_FILTER, + GST_DEBUG_CATEGORY_INIT (gst_video_analyse_debug_category, "videoanalyse", + 0, "debug category for videoanalyse element")); + +static void +gst_video_analyse_class_init (GstVideoAnalyseClass * klass) { - GstVideoAnalyse *vf; - GstStructure *in_s; - gboolean ret; + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass); - vf = GST_VIDEO_ANALYSE (btrans); + 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))); - in_s = gst_caps_get_structure (incaps, 0); + gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass), + "Video analyser", "Filter/Analyzer/Video", + "Analyse video signal", "Wim Taymans "); - ret = gst_structure_get_int (in_s, "width", &vf->width); - ret &= gst_structure_get_int (in_s, "height", &vf->height); + gobject_class->set_property = gst_video_analyse_set_property; + gobject_class->get_property = gst_video_analyse_get_property; + gobject_class->finalize = gst_video_analyse_finalize; + video_filter_class->transform_frame_ip = + GST_DEBUG_FUNCPTR (gst_video_analyse_transform_frame_ip); - return ret; + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MESSAGE, + g_param_spec_boolean ("message", "Message", + "Post statics messages", + DEFAULT_MESSAGE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + //trans_class->passthrough_on_same_caps = TRUE; } -/* Useful macros */ -#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) -#define GST_VIDEO_I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) -#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2) +static void +gst_video_analyse_init (GstVideoAnalyse * videoanalyse) +{ +} -#define GST_VIDEO_I420_Y_OFFSET(w,h) (0) -#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) -#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) +void +gst_video_analyse_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (object); -#define GST_VIDEO_I420_SIZE(w,h) (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + GST_DEBUG_OBJECT (videoanalyse, "set_property"); + + switch (property_id) { + case PROP_MESSAGE: + videoanalyse->message = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_video_analyse_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (object); + + GST_DEBUG_OBJECT (videoanalyse, "get_property"); + + switch (property_id) { + case PROP_MESSAGE: + g_value_set_boolean (value, videoanalyse->message); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_video_analyse_finalize (GObject * object) +{ + GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (object); + + GST_DEBUG_OBJECT (videoanalyse, "finalize"); + + /* clean up object here */ + + G_OBJECT_CLASS (gst_video_analyse_parent_class)->finalize (object); +} static void gst_video_analyse_post_message (GstVideoAnalyse * videoanalyse, - GstBuffer * buffer) + GstVideoFrame * frame) { GstBaseTransform *trans; GstMessage *m; @@ -160,8 +217,8 @@ gst_video_analyse_post_message (GstVideoAnalyse * videoanalyse, trans = GST_BASE_TRANSFORM_CAST (videoanalyse); /* get timestamps */ - timestamp = GST_BUFFER_TIMESTAMP (buffer); - duration = GST_BUFFER_DURATION (buffer); + timestamp = GST_BUFFER_TIMESTAMP (frame->buffer); + duration = GST_BUFFER_DURATION (frame->buffer); running_time = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME, timestamp); stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, @@ -173,35 +230,38 @@ gst_video_analyse_post_message (GstVideoAnalyse * videoanalyse, "stream-time", G_TYPE_UINT64, stream_time, "running-time", G_TYPE_UINT64, running_time, "duration", G_TYPE_UINT64, duration, - "brightness", G_TYPE_DOUBLE, videoanalyse->brightness, - "brightness-variance", G_TYPE_DOUBLE, videoanalyse->brightness_var, - NULL)); + "luma-average", G_TYPE_DOUBLE, videoanalyse->luma_average, + "luma-variance", G_TYPE_DOUBLE, videoanalyse->luma_variance, NULL)); gst_element_post_message (GST_ELEMENT_CAST (videoanalyse), m); } static void -gst_video_analyse_420 (GstVideoAnalyse * videoanalyse, guint8 * data, - gint width, gint height) +gst_video_analyse_planar (GstVideoAnalyse * videoanalyse, GstVideoFrame * frame) { guint64 sum; gint avg, diff; gint i, j; guint8 *d; + gint width = frame->info.width; + gint height = frame->info.height; + gint stride; - d = data; + d = frame->data[0]; + stride = frame->info.stride[0]; sum = 0; /* do brightness as average of pixel brightness in 0.0 to 1.0 */ for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { sum += d[j]; } - d += GST_VIDEO_I420_Y_ROWSTRIDE (width); + d += stride; } avg = sum / (width * height); - videoanalyse->brightness = sum / (255.0 * width * height); + videoanalyse->luma_average = sum / (255.0 * width * height); - d = data; + d = frame->data[0]; + stride = frame->info.stride[0]; sum = 0; /* do variance */ for (i = 0; i < height; i++) { @@ -209,141 +269,23 @@ gst_video_analyse_420 (GstVideoAnalyse * videoanalyse, guint8 * data, diff = (avg - d[j]); sum += diff * diff; } - d += GST_VIDEO_I420_Y_ROWSTRIDE (width); + d += stride; } - videoanalyse->brightness_var = sum / (255.0 * 255.0 * width * height); + videoanalyse->luma_variance = sum / (255.0 * 255.0 * width * height); } static GstFlowReturn -gst_video_analyse_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +gst_video_analyse_transform_frame_ip (GstVideoFilter * filter, + GstVideoFrame * frame) { - GstVideoAnalyse *videoanalyse; - GstFlowReturn ret = GST_FLOW_OK; - guint8 *data; + GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (filter); - videoanalyse = GST_VIDEO_ANALYSE (trans); + GST_DEBUG_OBJECT (videoanalyse, "transform_frame_ip"); - data = GST_BUFFER_DATA (buf); - - gst_video_analyse_420 (videoanalyse, data, videoanalyse->width, - videoanalyse->height); + gst_video_analyse_planar (videoanalyse, frame); if (videoanalyse->message) - gst_video_analyse_post_message (videoanalyse, buf); + gst_video_analyse_post_message (videoanalyse, frame); - return ret; -} - -static void -gst_video_analyse_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVideoAnalyse *videoanalyse; - - videoanalyse = GST_VIDEO_ANALYSE (object); - - switch (prop_id) { - case PROP_MESSAGE: - videoanalyse->message = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_video_analyse_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstVideoAnalyse *videoanalyse; - - videoanalyse = GST_VIDEO_ANALYSE (object); - - switch (prop_id) { - case PROP_MESSAGE: - g_value_set_boolean (value, videoanalyse->message); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_video_analyse_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_static_metadata (element_class, "Video analyser", - "Filter/Analyzer/Video", - "Analyse video signal", "Wim Taymans "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_video_analyse_sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_video_analyse_src_template)); -} - -static void -gst_video_analyse_class_init (gpointer klass, gpointer class_data) -{ - GObjectClass *gobject_class; - GstBaseTransformClass *trans_class; - - gobject_class = (GObjectClass *) klass; - trans_class = (GstBaseTransformClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->set_property = gst_video_analyse_set_property; - gobject_class->get_property = gst_video_analyse_get_property; - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MESSAGE, - g_param_spec_boolean ("message", "Message", - "Post statics messages", - DEFAULT_MESSAGE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - - trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_analyse_set_caps); - trans_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_video_analyse_transform_ip); - trans_class->passthrough_on_same_caps = TRUE; -} - -static void -gst_video_analyse_init (GTypeInstance * instance, gpointer g_class) -{ - GstVideoAnalyse *videoanalyse; - - videoanalyse = GST_VIDEO_ANALYSE (instance); - - GST_DEBUG_OBJECT (videoanalyse, "gst_video_analyse_init"); -} - -GType -gst_video_analyse_get_type (void) -{ - static GType video_analyse_type = 0; - - if (!video_analyse_type) { - static const GTypeInfo video_analyse_info = { - sizeof (GstVideoAnalyseClass), - gst_video_analyse_base_init, - NULL, - gst_video_analyse_class_init, - NULL, - NULL, - sizeof (GstVideoAnalyse), - 0, - gst_video_analyse_init, - }; - - video_analyse_type = g_type_register_static (GST_TYPE_VIDEO_FILTER, - "GstVideoAnalyse", &video_analyse_info, 0); - - GST_DEBUG_CATEGORY_INIT (video_analyse_debug, "videoanalyse", 0, - "Video Analyse element"); - } - return video_analyse_type; + return GST_FLOW_OK; } diff --git a/gst/videosignal/gstvideoanalyse.h b/gst/videosignal/gstvideoanalyse.h index c4949e5da9..ee61672b26 100644 --- a/gst/videosignal/gstvideoanalyse.h +++ b/gst/videosignal/gstvideoanalyse.h @@ -17,51 +17,41 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GST_VIDEO_ANALYSE_H__ -#define __GST_VIDEO_ANALYSE_H__ +#ifndef _GST_VIDEO_ANALYSE_H_ +#define _GST_VIDEO_ANALYSE_H_ +#include #include G_BEGIN_DECLS -#define GST_TYPE_VIDEO_ANALYSE \ - (gst_video_analyse_get_type()) -#define GST_VIDEO_ANALYSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_ANALYSE,GstVideoAnalyse)) -#define GST_VIDEO_ANALYSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_ANALYSE,GstVideoAnalyseClass)) -#define GST_IS_VIDEO_ANALYSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_ANALYSE)) -#define GST_IS_VIDEO_ANALYSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_ANALYSE)) +#define GST_TYPE_VIDEO_ANALYSE (gst_video_analyse_get_type()) +#define GST_VIDEO_ANALYSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_ANALYSE,GstVideoAnalyse)) +#define GST_VIDEO_ANALYSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_ANALYSE,GstVideoAnalyseClass)) +#define GST_IS_VIDEO_ANALYSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_ANALYSE)) +#define GST_IS_VIDEO_ANALYSE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_ANALYSE)) typedef struct _GstVideoAnalyse GstVideoAnalyse; typedef struct _GstVideoAnalyseClass GstVideoAnalyseClass; -/** - * GstVideoAnalyse: - * - * Opaque datastructure. - */ -struct _GstVideoAnalyse { - GstVideoFilter videofilter; - - gint width, height; +struct _GstVideoAnalyse +{ + GstVideoFilter base_videoanalyse; + /* properties */ gboolean message; - - gdouble brightness; - gdouble brightness_var; - guint64 interval; + gdouble luma_average; + gdouble luma_variance; }; -struct _GstVideoAnalyseClass { - GstVideoFilterClass parent_class; +struct _GstVideoAnalyseClass +{ + GstVideoFilterClass base_videoanalyse_class; }; GType gst_video_analyse_get_type (void); G_END_DECLS -#endif /* __GST_VIDEO_ANALYSE_H__ */ +#endif diff --git a/gst/videosignal/gstvideosignal.c b/gst/videosignal/gstvideosignal.c index 260f0ce614..8c20b3d2b7 100644 --- a/gst/videosignal/gstvideosignal.c +++ b/gst/videosignal/gstvideosignal.c @@ -30,12 +30,13 @@ plugin_init (GstPlugin * plugin) { gboolean res; + res = gst_element_register (plugin, "videoanalyse", GST_RANK_NONE, + GST_TYPE_VIDEO_ANALYSE); + #if 0 /* FIXME under no circumstances is anyone allowed to revive the * element formerly known as videodetect without changing the name * first. XOXO --ds */ - res = gst_element_register (plugin, "videoanalyse", GST_RANK_NONE, - GST_TYPE_VIDEO_ANALYSE); res &= gst_element_register (plugin, "videodetect", GST_RANK_NONE, GST_TYPE_VIDEO_DETECT);