From: Nicola Murino Date: Sat, 1 Sep 2012 18:46:43 +0000 (+0200) Subject: facedetect: new property to control bus messages updates X-Git-Tag: 1.19.3~507^2~13146 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e481ecbf2229468873296b350c1ff5b3ea28a71f;p=platform%2Fupstream%2Fgstreamer.git facedetect: new property to control bus messages updates https://bugzilla.gnome.org/show_bug.cgi?id=655622 --- diff --git a/ext/opencv/gstfacedetect.c b/ext/opencv/gstfacedetect.c index df548b0..18ac240 100644 --- a/ext/opencv/gstfacedetect.c +++ b/ext/opencv/gstfacedetect.c @@ -113,7 +113,8 @@ enum PROP_MIN_NEIGHBORS, PROP_FLAGS, PROP_MIN_SIZE_WIDTH, - PROP_MIN_SIZE_HEIGHT + PROP_MIN_SIZE_HEIGHT, + PROP_UPDATES }; @@ -150,6 +151,32 @@ gst_opencv_face_detect_flags_get_type (void) return id; } +#define GST_TYPE_FACE_DETECT_UPDATES (facedetect_update_get_type ()) + +static GType +facedetect_update_get_type (void) +{ + static GType facedetect_update_type = 0; + static const GEnumValue facedetect_update[] = { + {GST_FACEDETECT_UPDATES_EVERY_FRAME, "Send update messages on every frame", + "every_frame"}, + {GST_FACEDETECT_UPDATES_ON_CHANGE, + "Send update messages on change (face detected/not detected)", + "on_change"}, + {GST_FACEDETECT_UPDATES_ON_FACE, + "Send update messages when a face is detected", + "on_face"}, + {GST_FACEDETECT_UPDATES_NONE, "Send no messages update", "none"}, + {0, NULL, NULL}, + }; + + if (!facedetect_update_type) { + facedetect_update_type = + g_enum_register_static ("GstFaceDetectUpdates", facedetect_update); + } + return facedetect_update_type; +} + /* the capabilities of the inputs and outputs. */ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", @@ -270,6 +297,11 @@ gst_face_detect_class_init (GstFaceDetectClass * klass) g_param_spec_int ("min-size-height", "Minimum face height", "Minimum area height to be recognized as a face", 0, G_MAXINT, DEFAULT_MIN_SIZE_HEIGHT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_UPDATES, + g_param_spec_enum ("updates", "Updates", + "When send update bus messages, if at all", + GST_TYPE_FACE_DETECT_UPDATES, GST_FACEDETECT_UPDATES_EVERY_FRAME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gst_element_class_set_static_metadata (element_class, "facedetect", @@ -294,6 +326,7 @@ gst_face_detect_init (GstFaceDetect * filter) filter->mouth_profile = g_strdup (DEFAULT_MOUTH_PROFILE); filter->eyes_profile = g_strdup (DEFAULT_EYES_PROFILE); filter->display = TRUE; + filter->face_detected = FALSE; filter->scale_factor = DEFAULT_SCALE_FACTOR; filter->min_neighbors = DEFAULT_MIN_NEIGHBORS; filter->flags = DEFAULT_FLAGS; @@ -310,6 +343,7 @@ gst_face_detect_init (GstFaceDetect * filter) gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST (filter), TRUE); + filter->updates = GST_FACEDETECT_UPDATES_EVERY_FRAME; } static void @@ -369,6 +403,9 @@ gst_face_detect_set_property (GObject * object, guint prop_id, case PROP_FLAGS: filter->flags = g_value_get_flags (value); break; + case PROP_UPDATES: + filter->updates = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -412,6 +449,9 @@ gst_face_detect_get_property (GObject * object, guint prop_id, case PROP_FLAGS: g_value_set_flags (value, filter->flags); break; + case PROP_UPDATES: + g_value_set_enum (value, filter->updates); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -497,6 +537,7 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, CvSeq *mouth = NULL, *nose = NULL, *eyes = NULL; gint i; gboolean do_display = FALSE; + gboolean post_msg = FALSE; if (filter->display) { if (gst_buffer_is_writable (buf)) { @@ -512,8 +553,40 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, faces = gst_face_detect_run_detector (filter, filter->cvFaceDetect, filter->min_size_width, filter->min_size_height); - msg = gst_face_detect_message_new (filter, buf); - g_value_init (&facelist, GST_TYPE_LIST); + switch (filter->updates) { + case GST_FACEDETECT_UPDATES_EVERY_FRAME: + post_msg = TRUE; + break; + case GST_FACEDETECT_UPDATES_ON_CHANGE: + if (faces && faces->total > 0) { + post_msg = TRUE; + } else { + if (filter->face_detected) { + post_msg = TRUE; + } + } + break; + case GST_FACEDETECT_UPDATES_ON_FACE: + if (faces && faces->total > 0) { + post_msg = TRUE; + } else { + post_msg = FALSE; + } + break; + case GST_FACEDETECT_UPDATES_NONE: + post_msg = FALSE; + break; + default: + post_msg = TRUE; + break; + } + + filter->face_detected = faces ? faces->total > 0 : FALSE; + + if (post_msg) { + msg = gst_face_detect_message_new (filter, buf); + g_value_init (&facelist, GST_TYPE_LIST); + } for (i = 0; i < (faces ? faces->total : 0); i++) { CvRect *r = (CvRect *) cvGetSeqElem (faces, i); @@ -573,48 +646,49 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, "%2d/%2d: x,y = %4u,%4u: w.h = %4u,%4u : features(e,n,m) = %d,%d,%d", i, faces->total, r->x, r->y, r->width, r->height, have_eyes, have_nose, have_mouth); + if (post_msg) { + s = gst_structure_new ("face", + "x", G_TYPE_UINT, r->x, + "y", G_TYPE_UINT, r->y, + "width", G_TYPE_UINT, r->width, + "height", G_TYPE_UINT, r->height, NULL); + if (have_nose) { + CvRect *sr = (CvRect *) cvGetSeqElem (nose, 0); + GST_LOG_OBJECT (filter, "nose/%d: x,y = %4u,%4u: w.h = %4u,%4u", + nose->total, rnx + sr->x, rny + sr->y, sr->width, sr->height); + gst_structure_set (s, + "nose->x", G_TYPE_UINT, rnx + sr->x, + "nose->y", G_TYPE_UINT, rny + sr->y, + "nose->width", G_TYPE_UINT, sr->width, + "nose->height", G_TYPE_UINT, sr->height, NULL); + } + if (have_mouth) { + CvRect *sr = (CvRect *) cvGetSeqElem (mouth, 0); + GST_LOG_OBJECT (filter, "mouth/%d: x,y = %4u,%4u: w.h = %4u,%4u", + mouth->total, rmx + sr->x, rmy + sr->y, sr->width, sr->height); + gst_structure_set (s, + "mouth->x", G_TYPE_UINT, rmx + sr->x, + "mouth->y", G_TYPE_UINT, rmy + sr->y, + "mouth->width", G_TYPE_UINT, sr->width, + "mouth->height", G_TYPE_UINT, sr->height, NULL); + } + if (have_eyes) { + CvRect *sr = (CvRect *) cvGetSeqElem (eyes, 0); + GST_LOG_OBJECT (filter, "eyes/%d: x,y = %4u,%4u: w.h = %4u,%4u", + eyes->total, rex + sr->x, rey + sr->y, sr->width, sr->height); + gst_structure_set (s, + "eyes->x", G_TYPE_UINT, rex + sr->x, + "eyes->y", G_TYPE_UINT, rey + sr->y, + "eyes->width", G_TYPE_UINT, sr->width, + "eyes->height", G_TYPE_UINT, sr->height, NULL); + } - s = gst_structure_new ("face", - "x", G_TYPE_UINT, r->x, - "y", G_TYPE_UINT, r->y, - "width", G_TYPE_UINT, r->width, - "height", G_TYPE_UINT, r->height, NULL); - if (have_nose) { - CvRect *sr = (CvRect *) cvGetSeqElem (nose, 0); - GST_LOG_OBJECT (filter, "nose/%d: x,y = %4u,%4u: w.h = %4u,%4u", - nose->total, rnx + sr->x, rny + sr->y, sr->width, sr->height); - gst_structure_set (s, - "nose->x", G_TYPE_UINT, rnx + sr->x, - "nose->y", G_TYPE_UINT, rny + sr->y, - "nose->width", G_TYPE_UINT, sr->width, - "nose->height", G_TYPE_UINT, sr->height, NULL); - } - if (have_mouth) { - CvRect *sr = (CvRect *) cvGetSeqElem (mouth, 0); - GST_LOG_OBJECT (filter, "mouth/%d: x,y = %4u,%4u: w.h = %4u,%4u", - mouth->total, rmx + sr->x, rmy + sr->y, sr->width, sr->height); - gst_structure_set (s, - "mouth->x", G_TYPE_UINT, rmx + sr->x, - "mouth->y", G_TYPE_UINT, rmy + sr->y, - "mouth->width", G_TYPE_UINT, sr->width, - "mouth->height", G_TYPE_UINT, sr->height, NULL); + g_value_init (&facedata, GST_TYPE_STRUCTURE); + g_value_take_boxed (&facedata, s); + gst_value_list_append_value (&facelist, &facedata); + g_value_unset (&facedata); + s = NULL; } - if (have_eyes) { - CvRect *sr = (CvRect *) cvGetSeqElem (eyes, 0); - GST_LOG_OBJECT (filter, "eyes/%d: x,y = %4u,%4u: w.h = %4u,%4u", - eyes->total, rex + sr->x, rey + sr->y, sr->width, sr->height); - gst_structure_set (s, - "eyes->x", G_TYPE_UINT, rex + sr->x, - "eyes->y", G_TYPE_UINT, rey + sr->y, - "eyes->width", G_TYPE_UINT, sr->width, - "eyes->height", G_TYPE_UINT, sr->height, NULL); - } - - g_value_init (&facedata, GST_TYPE_STRUCTURE); - g_value_take_boxed (&facedata, s); - gst_value_list_append_value (&facelist, &facedata); - g_value_unset (&facedata); - s = NULL; if (do_display) { CvPoint center; @@ -674,10 +748,12 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, (guint) r->x, (guint) r->y, (guint) r->width, (guint) r->height); } - gst_structure_set_value ((GstStructure *) gst_message_get_structure (msg), - "faces", &facelist); - g_value_unset (&facelist); - gst_element_post_message (GST_ELEMENT (filter), msg); + if (post_msg) { + gst_structure_set_value ((GstStructure *) gst_message_get_structure (msg), + "faces", &facelist); + g_value_unset (&facelist); + gst_element_post_message (GST_ELEMENT (filter), msg); + } } return GST_FLOW_OK; diff --git a/ext/opencv/gstfacedetect.h b/ext/opencv/gstfacedetect.h index bd48c04..ac51c52 100644 --- a/ext/opencv/gstfacedetect.h +++ b/ext/opencv/gstfacedetect.h @@ -70,11 +70,28 @@ G_BEGIN_DECLS typedef struct _GstFaceDetect GstFaceDetect; typedef struct _GstFaceDetectClass GstFaceDetectClass; +/** + * GstFaceDetectUpdates + * @GST_FACEDETECT_UPDATES_EVERY_FRAME: Send bus update messages for every frame + * @GST_FACEDETECT_UPDATES_ON_CHANGE: Send bus update messages on change (face detected/not detected) + * @GST_FACEDETECT_UPDATES_ON_FACE: Send bus update messages when a face is detected + * @GST_FACEDETECT_UPDATES_NONE: No bus update messages + * + * Bus messages update scheme + */ +enum _GstFaceDetectUpdates { + GST_FACEDETECT_UPDATES_EVERY_FRAME = 0, + GST_FACEDETECT_UPDATES_ON_CHANGE = 1, + GST_FACEDETECT_UPDATES_ON_FACE = 2, + GST_FACEDETECT_UPDATES_NONE = 3 +}; + struct _GstFaceDetect { GstOpencvVideoFilter element; gboolean display; + gboolean face_detected; gchar *face_profile; gchar *nose_profile; @@ -85,6 +102,7 @@ struct _GstFaceDetect gint flags; gint min_size_width; gint min_size_height; + gint updates; IplImage *cvGray; CvHaarClassifierCascade *cvFaceDetect;