From fead44ad128ddbb054d108ce9489233a04069d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 15:47:24 +0000 Subject: faceoverlay: minor cosmetic changes Remove template maker comments, use our defines for package name and origin. --- gst/faceoverlay/gstfaceoverlay.c | 42 ++-------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index 209f656b4..1140f1c84 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -1,5 +1,4 @@ -/* - * GStreamer faceoverlay plugin +/* GStreamer faceoverlay plugin * Copyright (C) 2011 Laura Lucas Alday * * Permission is hereby granted, free of charge, to any person obtaining a @@ -76,13 +75,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_face_overlay_debug); #define GST_STR_VIDEO_CAPS GST_VIDEO_CAPS_ARGB #endif -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - enum { PROP_0, @@ -319,9 +311,6 @@ gst_face_overlay_message_handler (GstBin * bin, GstMessage * message) GST_BIN_CLASS (parent_class)->handle_message (bin, message); } -/* GObject vmethod implementations */ -/* the _base_init() function is meant to initialize class and child class - * properties during each new child class creation */ static void gst_face_overlay_base_init (gpointer gclass) { @@ -337,10 +326,6 @@ gst_face_overlay_base_init (gpointer gclass) gst_element_class_add_static_pad_template (element_class, &sink_factory); } -/* initialize the faceoverlay's class */ -/* the _class_init() function is used to initialise the class only once - * (specifying what signals, arguments and virtual functions the class has and - * setting up global state) */ static void gst_face_overlay_class_init (GstFaceOverlayClass * klass) { @@ -380,15 +365,8 @@ gst_face_overlay_class_init (GstFaceOverlayClass * klass) GST_DEBUG_FUNCPTR (gst_face_overlay_message_handler); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_face_overlay_change_state); - } -/* initialize the new element - * instantiate pads and add them to element - * set pad calback functions - * initialize instance structure - * the _init() function is used to initialise a specific instance of this type. - */ static void gst_face_overlay_init (GstFaceOverlay * filter, GstFaceOverlayClass * gclass) { @@ -407,7 +385,6 @@ gst_face_overlay_init (GstFaceOverlay * filter, GstFaceOverlayClass * gclass) filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - } static void @@ -466,14 +443,9 @@ gst_face_overlay_get_property (GObject * object, guint prop_id, } } -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and other features - */ static gboolean faceoverlay_init (GstPlugin * faceoverlay) { - /* debug category for fltering log messages */ GST_DEBUG_CATEGORY_INIT (gst_face_overlay_debug, "faceoverlay", 0, "SVG Face Overlay"); @@ -481,18 +453,8 @@ faceoverlay_init (GstPlugin * faceoverlay) GST_TYPE_FACEOVERLAY); } -/* PACKAGE: this is usually set by autotools depending on some _INIT macro - * in configure.ac and then written into and defined in config.h, but we can - * just set it ourselves here in case someone doesn't use autotools to - * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined. - */ -#ifndef PACKAGE -#define PACKAGE "faceoverlay" -#endif - -/* gstreamer looks for this structure to register plugins */ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "faceoverlay", "SVG Face Overlay", - faceoverlay_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") + faceoverlay_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) -- cgit v1.2.1 From d405ea2e632363e560dd3784177f249196bb2bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 16:52:44 +0000 Subject: faceoverlay: fix weird pad creation code The element would create normal pads in its instance_init function, and then later in NULL->READY create the elements it needs, remove the pads created in the instance_init function, and add new ghost pads instead. Not without saving the external peer pads of the old pads of course, which it would promptly re-link to the new ghost pads. Do all of that a bit differently. Fixes the generic/states.check unit test. https://bugzilla.gnome.org/show_bug.cgi?id=670588 --- gst/faceoverlay/gstfaceoverlay.c | 158 +++++++++++++-------------------------- gst/faceoverlay/gstfaceoverlay.h | 7 +- 2 files changed, 57 insertions(+), 108 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index 1140f1c84..dd3818911 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -109,121 +109,62 @@ static void gst_face_overlay_message_handler (GstBin * bin, static GstStateChangeReturn gst_face_overlay_change_state (GstElement * element, GstStateChange transition); static gboolean gst_face_overlay_create_children (GstFaceOverlay * filter); -static gboolean gst_face_overlay_reset (GstFaceOverlay * filter); -static gboolean gst_face_overlay_create_pad (GstFaceOverlay * filter, - GstPad * filter_pad, const char *pad_name, GstElement * child_element); -static gboolean toggle_pads_link_state (GstPad * pad1, GstPad * pad2); - -static gboolean -toggle_pads_link_state (GstPad * pad1, GstPad * pad2) -{ - gboolean ok = TRUE; - - if (gst_pad_is_linked (pad1)) { - if (gst_pad_get_direction (pad1) == GST_PAD_SINK) - gst_pad_unlink (pad2, pad1); - else - gst_pad_unlink (pad1, pad2); - } else { - if (gst_pad_get_direction (pad1) == GST_PAD_SINK) - ok &= (gst_pad_link (pad2, pad1) == 0); - else - ok &= (gst_pad_link (pad1, pad2) == 0); - } - - return ok; -} - -/* Unlinks and removes the pad that was created in gst_face_overlay_init () - * and adds the internal element ghost pad instead */ static gboolean -gst_face_overlay_create_pad (GstFaceOverlay * filter, GstPad * filter_pad, - const char *pad_name, GstElement * child_element) +gst_face_overlay_create_children (GstFaceOverlay * filter) { - GstPad *peer = NULL; - GstPad *pad = NULL; - gboolean ok = TRUE; - - /* get the outside world pad connected to faceoverlay src/sink pad */ - peer = gst_pad_get_peer (filter_pad); - - /* unlink and remove the faceoverlay src/sink pad */ - toggle_pads_link_state (peer, filter_pad); - - gst_element_remove_pad (GST_ELEMENT (filter), filter_pad); - - /* add a ghost pad pointing to the child element pad (facedetect sink or - * svg_overlay src depending on filter_pad direction) and add it to - * faceoverlay bin */ - pad = gst_element_get_static_pad (child_element, pad_name); - filter_pad = gst_ghost_pad_new (pad_name, pad); - gst_object_unref (GST_OBJECT (pad)); + GstElement *csp, *face_detect, *overlay; + GstPad *pad; - gst_element_add_pad (GST_ELEMENT (filter), filter_pad); + csp = gst_element_factory_make ("ffmpegcolorspace", NULL); + face_detect = gst_element_factory_make ("facedetect", NULL); + overlay = gst_element_factory_make ("rsvgoverlay", NULL); - /* link the child element pad to the outside world thru the ghost pad */ - toggle_pads_link_state (peer, filter_pad); + /* FIXME: post missing-plugin messages on NULL->READY if needed */ + if (csp == NULL || face_detect == NULL || overlay == NULL) + goto missing_element; - g_object_unref (peer); + g_object_set (face_detect, "display", FALSE, NULL); - return ok; -} + gst_bin_add_many (GST_BIN (filter), face_detect, csp, overlay, NULL); + filter->svg_overlay = overlay; -static gboolean -gst_face_overlay_reset (GstFaceOverlay * filter) -{ - gst_element_set_state (filter->face_detect, GST_STATE_NULL); - gst_bin_remove (GST_BIN (filter), filter->face_detect); - filter->face_detect = NULL; + if (!gst_element_link_many (face_detect, csp, overlay, NULL)) + GST_ERROR_OBJECT (filter, "couldn't link elements"); - gst_element_set_state (filter->svg_overlay, GST_STATE_NULL); - gst_bin_remove (GST_BIN (filter), filter->svg_overlay); - filter->svg_overlay = NULL; + pad = gst_element_get_static_pad (face_detect, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (filter->sinkpad), pad)) + GST_ERROR_OBJECT (filter->sinkpad, "couldn't set sinkpad target"); + gst_object_unref (pad); - gst_element_set_state (filter->colorspace, GST_STATE_NULL); - gst_bin_remove (GST_BIN (filter), filter->colorspace); - filter->colorspace = NULL; + pad = gst_element_get_static_pad (overlay, "src"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (filter->srcpad), pad)) + GST_ERROR_OBJECT (filter->srcpad, "couldn't set srcpad target"); + gst_object_unref (pad); return TRUE; -} -static gboolean -gst_face_overlay_create_children (GstFaceOverlay * filter) -{ - gboolean ret = TRUE; +/* ERRORS */ +missing_element: + { + /* clean up */ + if (csp == NULL) + GST_ERROR_OBJECT (filter, "ffmpegcolorspace element not found"); + else + gst_object_unref (csp); - if ((filter->colorspace = gst_element_factory_make ("ffmpegcolorspace", - NULL)) == NULL) { - return FALSE; - } + if (face_detect == NULL) + GST_ERROR_OBJECT (filter, "facedetect element not found (opencv plugin)"); + else + gst_object_unref (face_detect); - if ((filter->face_detect = gst_element_factory_make ("facedetect", - NULL)) == NULL) { - return FALSE; - } - g_object_set (filter->face_detect, "display", 0, NULL); + if (overlay == NULL) + GST_ERROR_OBJECT (filter, "rsvgoverlay element not found (rsvg plugin)"); + else + gst_object_unref (overlay); - if ((filter->svg_overlay = gst_element_factory_make ("rsvgoverlay", - NULL)) == NULL) { return FALSE; } - - gst_bin_add_many (GST_BIN (filter), - filter->face_detect, filter->colorspace, filter->svg_overlay, NULL); - - ret &= gst_element_link_pads (filter->face_detect, "src", - filter->colorspace, "sink"); - ret &= gst_element_link_pads (filter->colorspace, "src", - filter->svg_overlay, "sink"); - - ret &= gst_face_overlay_create_pad (filter, filter->sinkpad, "sink", - filter->face_detect); - ret &= gst_face_overlay_create_pad (filter, filter->srcpad, "src", - filter->svg_overlay); - - return ret; - } static GstStateChangeReturn @@ -234,8 +175,12 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_face_overlay_create_children (filter)) + if (filter->svg_overlay == NULL) { + GST_ELEMENT_ERROR (filter, CORE, MISSING_PLUGIN, (NULL), + ("Some required plugins are missing, probably either the opencv " + "facedetect element or rsvgoverlay")); return GST_STATE_CHANGE_FAILURE; + } break; default: break; @@ -244,9 +189,6 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition) ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - gst_face_overlay_reset (filter); - break; default: break; } @@ -370,21 +312,27 @@ gst_face_overlay_class_init (GstFaceOverlayClass * klass) static void gst_face_overlay_init (GstFaceOverlay * filter, GstFaceOverlayClass * gclass) { + GstPadTemplate *tmpl; + filter->x = 0; filter->y = 0; filter->w = 1; filter->h = 1; - filter->colorspace = NULL; filter->svg_overlay = NULL; - filter->face_detect = NULL; filter->location = NULL; filter->process_message = TRUE; - filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); + tmpl = gst_static_pad_template_get (&sink_factory); + filter->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", tmpl); + gst_object_unref (tmpl); gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); - filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); + tmpl = gst_static_pad_template_get (&src_factory); + filter->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl); + gst_object_unref (tmpl); gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + + gst_face_overlay_create_children (filter); } static void diff --git a/gst/faceoverlay/gstfaceoverlay.h b/gst/faceoverlay/gstfaceoverlay.h index 7b8e50c00..7f4427c28 100644 --- a/gst/faceoverlay/gstfaceoverlay.h +++ b/gst/faceoverlay/gstfaceoverlay.h @@ -1,5 +1,4 @@ -/* - * GStreamer faceoverlay plugin +/* GStreamer faceoverlay plugin * Copyright (C) 2011 Laura Lucas Alday * * Permission is hereby granted, free of charge, to any person obtaining a @@ -47,7 +46,7 @@ #include G_BEGIN_DECLS -/* #defines don't like whitespacey bits */ + #define GST_TYPE_FACEOVERLAY \ (gst_face_overlay_get_type()) #define GST_FACEOVERLAY(obj) \ @@ -58,6 +57,7 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FACEOVERLAY)) #define GST_IS_FACEOVERLAY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FACEOVERLAY)) + typedef struct _GstFaceOverlay GstFaceOverlay; typedef struct _GstFaceOverlayClass GstFaceOverlayClass; @@ -88,4 +88,5 @@ struct _GstFaceOverlayClass GType gst_face_overlay_get_type (void); G_END_DECLS + #endif /* __GST_FACEOVERLAY_H__ */ -- cgit v1.2.1 From 55b0f1e60168571ebbbd7a99ab51a687607a6619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 17:42:56 +0000 Subject: faceoverlay: fix pad templates Use generic and unspecififed rgb/caps for now. The exact caps supported depend on the facedetect element and rsvgoverlay. It's not clear how this worked before, since facedetect only accepts 24-bit RGB, but the caps advertised 32-bit ARGB/BGRA. In any case, we don't want to force anything really, so that if any of those elements acquires support for additional formats we pick those up automatically. --- gst/faceoverlay/gstfaceoverlay.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index dd3818911..ebb2de9b8 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -69,12 +69,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_face_overlay_debug); #define GST_CAT_DEFAULT gst_face_overlay_debug -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define GST_STR_VIDEO_CAPS GST_VIDEO_CAPS_BGRA -#else -#define GST_STR_VIDEO_CAPS GST_VIDEO_CAPS_ARGB -#endif - enum { PROP_0, @@ -85,17 +79,16 @@ enum PROP_H }; -/* the capabilities of the inputs and outputs. */ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_STR_VIDEO_CAPS) + GST_STATIC_CAPS ("video/x-raw-rgb; video/x-raw-yuv") ); static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_STR_VIDEO_CAPS) + GST_STATIC_CAPS ("video/x-raw-rgb; video/x-raw-yuv") ); GST_BOILERPLATE (GstFaceOverlay, gst_face_overlay, GstBin, GST_TYPE_BIN); -- cgit v1.2.1 From 549447d2880b6af7a59967039b34675f9b92eb73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 17:47:58 +0000 Subject: faceoverlay: move face handling into own function and handle 0 face count When a face disappears, we seem to get a message from facedetect with a face count of 0, which we want to just ignore instead of trying to access face #-1, which causes nasty warnings. --- gst/faceoverlay/gstfaceoverlay.c | 106 +++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 48 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index ebb2de9b8..b3442b2bc 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -189,58 +189,68 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition) return ret; } +static void +gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) +{ + guint x, y, width, height; + int delta_x, delta_y, svg_x, svg_y, svg_width, svg_height; + const GstStructure *face; + const GValue *faces_list, *face_val; + int face_count; + +#if 0 + /* optionally draw the image once every two messages for better performance */ + filter->process_message = !filter->process_message; + if (!filter->process_message) + return; +#endif + + faces_list = gst_structure_get_value (s, "faces"); + face_count = gst_value_list_get_size (faces_list); + GST_LOG_OBJECT (filter, "face count: %d", face_count); + + /* FIXME: should we clear the overlay in this case? */ + if (face_count == 0) + return; + + /* The last face in the list seems to be the right one, objects mistakenly + * detected as faces for a couple of frames seem to be in the list + * beginning. TODO: needs confirmation. */ + face_val = gst_value_list_get_value (faces_list, face_count - 1); + face = gst_value_get_structure (face_val); + gst_structure_get_uint (face, "x", &x); + gst_structure_get_uint (face, "y", &y); + gst_structure_get_uint (face, "width", &width); + gst_structure_get_uint (face, "height", &height); + + /* Apply x and y offsets relative to face position and size. + * Set image width and height as a fraction of face width and height. + * Cast to int since face position and size will never be bigger than + * G_MAX_INT and we may have negative values as svg_x or svg_y */ + + delta_x = (int) (filter->x * (int) width); + svg_x = (int) x + delta_x; + + delta_y = (int) (filter->y * (int) height); + svg_y = (int) y + delta_y; + + svg_width = (int) width *filter->w; + svg_height = (int) height *filter->h; + + GST_LOG_OBJECT (filter, "setting overlay to %d x %d @ %d,%d (file: %s)", + svg_width, svg_height, svg_x, svg_y, GST_STR_NULL (filter->location)); + + g_object_set (filter->svg_overlay, + "location", filter->location, + "x", svg_x, "y", svg_y, "width", svg_width, "height", svg_height, NULL); +} + static void gst_face_overlay_message_handler (GstBin * bin, GstMessage * message) { if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT && - strcmp (gst_structure_get_name (message->structure), "facedetect") == 0) { - GstFaceOverlay *filter = GST_FACEOVERLAY (bin); - - /* optionally draw the image once every two messages for better performance - * filter->process_message = !filter->process_message; - * if(!filter->process_message) - * return; - */ - - guint x, y, width, height; - int delta_x, delta_y, svg_x, svg_y, svg_width, svg_height; - const GstStructure *face; - int face_count; - - face_count = - gst_value_list_get_size (gst_structure_get_value (message->structure, - "faces")); - - /* The last face in the list seems to be the right one, objects mistakenly - * detected as faces for a couple of frames seem to be in the list - * beginning. TODO: needs confirmation. */ - face = - gst_value_get_structure (gst_value_list_get_value - (gst_structure_get_value (message->structure, "faces"), - face_count - 1)); - gst_structure_get_uint (face, "x", &x); - gst_structure_get_uint (face, "y", &y); - gst_structure_get_uint (face, "width", &width); - gst_structure_get_uint (face, "height", &height); - - /* Apply x and y offsets relative to face position and size. - * Set image width and height as a fraction of face width and height. - * Cast to int since face position and size will never be bigger than - * G_MAX_INT and we may have negative values as svg_x or svg_y */ - - delta_x = (int) (filter->x * (int) width); - svg_x = (int) x + delta_x; - - delta_y = (int) (filter->y * (int) height); - svg_y = (int) y + delta_y; - - svg_width = (int) width *filter->w; - svg_height = (int) height *filter->h; - - g_object_set (filter->svg_overlay, - "location", filter->location, - "x", svg_x, "y", svg_y, "width", svg_width, "height", svg_height, NULL); - + gst_structure_has_name (message->structure, "facedetect")) { + gst_face_overlay_handle_faces (GST_FACEOVERLAY (bin), message->structure); } GST_BIN_CLASS (parent_class)->handle_message (bin, message); -- cgit v1.2.1 From 3bbb0387c48689597720e5ff337ac6929d448a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 18:08:09 +0000 Subject: faceoverlay: don't make rsvgoverlay reload the SVG for every single frame Only set location on rsvgoverlay if it has changed. --- gst/faceoverlay/gstfaceoverlay.c | 13 ++++++++++--- gst/faceoverlay/gstfaceoverlay.h | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index b3442b2bc..da3cb4070 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -174,6 +174,7 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition) "facedetect element or rsvgoverlay")); return GST_STATE_CHANGE_FAILURE; } + filter->update_svg = TRUE; break; default: break; @@ -237,11 +238,16 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) svg_width = (int) width *filter->w; svg_height = (int) height *filter->h; - GST_LOG_OBJECT (filter, "setting overlay to %d x %d @ %d,%d (file: %s)", - svg_width, svg_height, svg_x, svg_y, GST_STR_NULL (filter->location)); + if (filter->update_svg) { + GST_DEBUG_OBJECT (filter, "set rsvgoverlay location=%s", filter->location); + g_object_set (filter->svg_overlay, "location", filter->location, NULL); + filter->update_svg = FALSE; + } + + GST_LOG_OBJECT (filter, "overlay dimensions: %d x %d @ %d,%d", + svg_width, svg_height, svg_x, svg_y); g_object_set (filter->svg_overlay, - "location", filter->location, "x", svg_x, "y", svg_y, "width", svg_width, "height", svg_height, NULL); } @@ -347,6 +353,7 @@ gst_face_overlay_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: filter->location = g_value_dup_string (value); + filter->update_svg = TRUE; break; case PROP_X: filter->x = g_value_get_float (value); diff --git a/gst/faceoverlay/gstfaceoverlay.h b/gst/faceoverlay/gstfaceoverlay.h index 7f4427c28..c21327b11 100644 --- a/gst/faceoverlay/gstfaceoverlay.h +++ b/gst/faceoverlay/gstfaceoverlay.h @@ -73,6 +73,8 @@ struct _GstFaceOverlay gboolean process_message; + gboolean update_svg; + gchar *location; gfloat x; gfloat y; -- cgit v1.2.1 From 36a6a13f1c3a113b9a68dbd5362072ed937f7a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 18:21:37 +0000 Subject: faceoverlay: add some locking for properties, free previous location when it changes --- gst/faceoverlay/gstfaceoverlay.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index da3cb4070..9695f0aef 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -197,6 +197,7 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) int delta_x, delta_y, svg_x, svg_y, svg_width, svg_height; const GstStructure *face; const GValue *faces_list, *face_val; + gchar *new_location = NULL; int face_count; #if 0 @@ -229,6 +230,8 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) * Cast to int since face position and size will never be bigger than * G_MAX_INT and we may have negative values as svg_x or svg_y */ + GST_OBJECT_LOCK (filter); + delta_x = (int) (filter->x * (int) width); svg_x = (int) x + delta_x; @@ -239,10 +242,16 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) svg_height = (int) height *filter->h; if (filter->update_svg) { - GST_DEBUG_OBJECT (filter, "set rsvgoverlay location=%s", filter->location); - g_object_set (filter->svg_overlay, "location", filter->location, NULL); + new_location = g_strdup (filter->location); filter->update_svg = FALSE; } + GST_OBJECT_UNLOCK (filter); + + if (new_location != NULL) { + GST_DEBUG_OBJECT (filter, "set rsvgoverlay location=%s", new_location); + g_object_set (filter->svg_overlay, "location", new_location, NULL); + g_free (new_location); + } GST_LOG_OBJECT (filter, "overlay dimensions: %d x %d @ %d,%d", svg_width, svg_height, svg_x, svg_y); @@ -352,20 +361,31 @@ gst_face_overlay_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: + GST_OBJECT_LOCK (filter); + g_free (filter->location); filter->location = g_value_dup_string (value); filter->update_svg = TRUE; + GST_OBJECT_UNLOCK (filter); break; case PROP_X: + GST_OBJECT_LOCK (filter); filter->x = g_value_get_float (value); + GST_OBJECT_UNLOCK (filter); break; case PROP_Y: + GST_OBJECT_LOCK (filter); filter->y = g_value_get_float (value); + GST_OBJECT_UNLOCK (filter); break; case PROP_W: + GST_OBJECT_LOCK (filter); filter->w = g_value_get_float (value); + GST_OBJECT_UNLOCK (filter); break; case PROP_H: + GST_OBJECT_LOCK (filter); filter->h = g_value_get_float (value); + GST_OBJECT_UNLOCK (filter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -381,19 +401,29 @@ gst_face_overlay_get_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: + GST_OBJECT_LOCK (filter); g_value_set_string (value, filter->location); + GST_OBJECT_UNLOCK (filter); break; case PROP_X: + GST_OBJECT_LOCK (filter); g_value_set_float (value, filter->x); + GST_OBJECT_UNLOCK (filter); break; case PROP_Y: + GST_OBJECT_LOCK (filter); g_value_set_float (value, filter->y); + GST_OBJECT_UNLOCK (filter); break; case PROP_W: + GST_OBJECT_LOCK (filter); g_value_set_float (value, filter->w); + GST_OBJECT_UNLOCK (filter); break; case PROP_H: + GST_OBJECT_LOCK (filter); g_value_set_float (value, filter->h); + GST_OBJECT_UNLOCK (filter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -- cgit v1.2.1 From 3f07ebcc37b77ee7c39f964aab6e207eb7ff028f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 15 Mar 2012 18:26:24 +0000 Subject: faceoverlay: clear overlay if the face disappears --- gst/faceoverlay/gstfaceoverlay.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index 9695f0aef..67bd96ee4 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -211,9 +211,14 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) face_count = gst_value_list_get_size (faces_list); GST_LOG_OBJECT (filter, "face count: %d", face_count); - /* FIXME: should we clear the overlay in this case? */ - if (face_count == 0) + if (face_count == 0) { + GST_DEBUG_OBJECT (filter, "no face, clearing overlay"); + g_object_set (filter->svg_overlay, "location", NULL, NULL); + GST_OBJECT_LOCK (filter); + filter->update_svg = TRUE; + GST_OBJECT_UNLOCK (filter); return; + } /* The last face in the list seems to be the right one, objects mistakenly * detected as faces for a couple of frames seem to be in the list -- cgit v1.2.1 From a31a698943b2402da2e23886b46e61f9d143ce4e Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Thu, 15 Mar 2012 22:49:51 +0100 Subject: faceoverlay: don't access message fields directly --- gst/faceoverlay/gstfaceoverlay.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index 67bd96ee4..7d87fc726 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -191,7 +191,7 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition) } static void -gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) +gst_face_overlay_handle_faces (GstFaceOverlay * filter, const GstStructure * s) { guint x, y, width, height; int delta_x, delta_y, svg_x, svg_y, svg_width, svg_height; @@ -268,9 +268,12 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, GstStructure * s) static void gst_face_overlay_message_handler (GstBin * bin, GstMessage * message) { - if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT && - gst_structure_has_name (message->structure, "facedetect")) { - gst_face_overlay_handle_faces (GST_FACEOVERLAY (bin), message->structure); + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) { + const GstStructure *s = gst_message_get_structure (message); + + if (gst_structure_has_name (s, "facedetect")) { + gst_face_overlay_handle_faces (GST_FACEOVERLAY (bin), s); + } } GST_BIN_CLASS (parent_class)->handle_message (bin, message); -- cgit v1.2.1 From 288c6fa26cb87fad9d6695ac4e52f0a090379178 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Thu, 15 Mar 2012 22:58:11 +0100 Subject: faceoverlay: code cleanups Use glib types and simply expressions in the message handler. --- gst/faceoverlay/gstfaceoverlay.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index 7d87fc726..56c0522f3 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -194,11 +194,11 @@ static void gst_face_overlay_handle_faces (GstFaceOverlay * filter, const GstStructure * s) { guint x, y, width, height; - int delta_x, delta_y, svg_x, svg_y, svg_width, svg_height; + gint svg_x, svg_y, svg_width, svg_height; const GstStructure *face; const GValue *faces_list, *face_val; gchar *new_location = NULL; - int face_count; + gint face_count; #if 0 /* optionally draw the image once every two messages for better performance */ @@ -237,14 +237,11 @@ gst_face_overlay_handle_faces (GstFaceOverlay * filter, const GstStructure * s) GST_OBJECT_LOCK (filter); - delta_x = (int) (filter->x * (int) width); - svg_x = (int) x + delta_x; + svg_x = (gint) x + (gint) (filter->x * width); + svg_y = (gint) y + (gint) (filter->y * height); - delta_y = (int) (filter->y * (int) height); - svg_y = (int) y + delta_y; - - svg_width = (int) width *filter->w; - svg_height = (int) height *filter->h; + svg_width = (gint) (filter->w * width); + svg_height = (gint) (filter->h * height); if (filter->update_svg) { new_location = g_strdup (filter->location); -- cgit v1.2.1 From f8cf7bf9738210dfdbf639fad1bd28566304f488 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Fri, 16 Mar 2012 12:10:10 +0100 Subject: faceoverlay: remove blank line in gtk-doc comment --- gst/faceoverlay/gstfaceoverlay.c | 1 - 1 file changed, 1 deletion(-) (limited to 'gst/faceoverlay') diff --git a/gst/faceoverlay/gstfaceoverlay.c b/gst/faceoverlay/gstfaceoverlay.c index 56c0522f3..b923c8fb9 100644 --- a/gst/faceoverlay/gstfaceoverlay.c +++ b/gst/faceoverlay/gstfaceoverlay.c @@ -51,7 +51,6 @@ * Example launch line * |[ * gst-launch autovideosrc ! ffmpegcolorspace ! faceoverlay location=/path/to/gnome-video-effects/pixmaps/bow.svg x=-5 y=-15 w=0.3 h=0.1 ! ffmpegcolorspace ! autovideosink - * ]| * */ -- cgit v1.2.1