mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-23 14:36:24 +00:00
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
This commit is contained in:
parent
fead44ad12
commit
d405ea2e63
2 changed files with 68 additions and 119 deletions
|
@ -109,121 +109,62 @@ static void gst_face_overlay_message_handler (GstBin * bin,
|
||||||
static GstStateChangeReturn gst_face_overlay_change_state (GstElement * element,
|
static GstStateChangeReturn gst_face_overlay_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
static gboolean gst_face_overlay_create_children (GstFaceOverlay * filter);
|
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)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
|
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter_pad);
|
|
||||||
|
|
||||||
/* link the child element pad to the outside world thru the ghost pad */
|
|
||||||
toggle_pads_link_state (peer, filter_pad);
|
|
||||||
|
|
||||||
g_object_unref (peer);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
gst_element_set_state (filter->svg_overlay, GST_STATE_NULL);
|
|
||||||
gst_bin_remove (GST_BIN (filter), filter->svg_overlay);
|
|
||||||
filter->svg_overlay = NULL;
|
|
||||||
|
|
||||||
gst_element_set_state (filter->colorspace, GST_STATE_NULL);
|
|
||||||
gst_bin_remove (GST_BIN (filter), filter->colorspace);
|
|
||||||
filter->colorspace = NULL;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_face_overlay_create_children (GstFaceOverlay * filter)
|
gst_face_overlay_create_children (GstFaceOverlay * filter)
|
||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
GstElement *csp, *face_detect, *overlay;
|
||||||
|
GstPad *pad;
|
||||||
|
|
||||||
|
csp = gst_element_factory_make ("ffmpegcolorspace", NULL);
|
||||||
|
face_detect = gst_element_factory_make ("facedetect", NULL);
|
||||||
|
overlay = gst_element_factory_make ("rsvgoverlay", NULL);
|
||||||
|
|
||||||
|
/* FIXME: post missing-plugin messages on NULL->READY if needed */
|
||||||
|
if (csp == NULL || face_detect == NULL || overlay == NULL)
|
||||||
|
goto missing_element;
|
||||||
|
|
||||||
|
g_object_set (face_detect, "display", FALSE, NULL);
|
||||||
|
|
||||||
|
gst_bin_add_many (GST_BIN (filter), face_detect, csp, overlay, NULL);
|
||||||
|
filter->svg_overlay = overlay;
|
||||||
|
|
||||||
|
if (!gst_element_link_many (face_detect, csp, overlay, NULL))
|
||||||
|
GST_ERROR_OBJECT (filter, "couldn't link elements");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
missing_element:
|
||||||
|
{
|
||||||
|
/* clean up */
|
||||||
|
if (csp == NULL)
|
||||||
|
GST_ERROR_OBJECT (filter, "ffmpegcolorspace element not found");
|
||||||
|
else
|
||||||
|
gst_object_unref (csp);
|
||||||
|
|
||||||
|
if (face_detect == NULL)
|
||||||
|
GST_ERROR_OBJECT (filter, "facedetect element not found (opencv plugin)");
|
||||||
|
else
|
||||||
|
gst_object_unref (face_detect);
|
||||||
|
|
||||||
|
if (overlay == NULL)
|
||||||
|
GST_ERROR_OBJECT (filter, "rsvgoverlay element not found (rsvg plugin)");
|
||||||
|
else
|
||||||
|
gst_object_unref (overlay);
|
||||||
|
|
||||||
if ((filter->colorspace = gst_element_factory_make ("ffmpegcolorspace",
|
|
||||||
NULL)) == NULL) {
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((filter->face_detect = gst_element_factory_make ("facedetect",
|
|
||||||
NULL)) == NULL) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_object_set (filter->face_detect, "display", 0, NULL);
|
|
||||||
|
|
||||||
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
|
static GstStateChangeReturn
|
||||||
|
@ -234,8 +175,12 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
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;
|
return GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -244,9 +189,6 @@ gst_face_overlay_change_state (GstElement * element, GstStateChange transition)
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
||||||
gst_face_overlay_reset (filter);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -370,21 +312,27 @@ gst_face_overlay_class_init (GstFaceOverlayClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_face_overlay_init (GstFaceOverlay * filter, GstFaceOverlayClass * gclass)
|
gst_face_overlay_init (GstFaceOverlay * filter, GstFaceOverlayClass * gclass)
|
||||||
{
|
{
|
||||||
|
GstPadTemplate *tmpl;
|
||||||
|
|
||||||
filter->x = 0;
|
filter->x = 0;
|
||||||
filter->y = 0;
|
filter->y = 0;
|
||||||
filter->w = 1;
|
filter->w = 1;
|
||||||
filter->h = 1;
|
filter->h = 1;
|
||||||
filter->colorspace = NULL;
|
|
||||||
filter->svg_overlay = NULL;
|
filter->svg_overlay = NULL;
|
||||||
filter->face_detect = NULL;
|
|
||||||
filter->location = NULL;
|
filter->location = NULL;
|
||||||
filter->process_message = TRUE;
|
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);
|
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_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
||||||
|
|
||||||
|
gst_face_overlay_create_children (filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/*
|
/* GStreamer faceoverlay plugin
|
||||||
* GStreamer faceoverlay plugin
|
|
||||||
* Copyright (C) 2011 Laura Lucas Alday <lauralucas@gmail.com>
|
* Copyright (C) 2011 Laura Lucas Alday <lauralucas@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -47,7 +46,7 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
/* #defines don't like whitespacey bits */
|
|
||||||
#define GST_TYPE_FACEOVERLAY \
|
#define GST_TYPE_FACEOVERLAY \
|
||||||
(gst_face_overlay_get_type())
|
(gst_face_overlay_get_type())
|
||||||
#define GST_FACEOVERLAY(obj) \
|
#define GST_FACEOVERLAY(obj) \
|
||||||
|
@ -58,6 +57,7 @@ G_BEGIN_DECLS
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FACEOVERLAY))
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FACEOVERLAY))
|
||||||
#define GST_IS_FACEOVERLAY_CLASS(klass) \
|
#define GST_IS_FACEOVERLAY_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FACEOVERLAY))
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FACEOVERLAY))
|
||||||
|
|
||||||
typedef struct _GstFaceOverlay GstFaceOverlay;
|
typedef struct _GstFaceOverlay GstFaceOverlay;
|
||||||
typedef struct _GstFaceOverlayClass GstFaceOverlayClass;
|
typedef struct _GstFaceOverlayClass GstFaceOverlayClass;
|
||||||
|
|
||||||
|
@ -88,4 +88,5 @@ struct _GstFaceOverlayClass
|
||||||
GType gst_face_overlay_get_type (void);
|
GType gst_face_overlay_get_type (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_FACEOVERLAY_H__ */
|
#endif /* __GST_FACEOVERLAY_H__ */
|
||||||
|
|
Loading…
Reference in a new issue