/* GST_PLUGIN_PATH=. GST_REGISTRY=./registry.xml GST_DEBUG=*:5 \ gst-launch-0.10 videotestsrc ! ffmpegcolorspace name=precsp ! \ cvbgsubtraction ! \ ffmpegcolorspace name=postcsp ! ximagesink \ 2>debug.log ERROR: from element /pipeline0/videotestsrc0: Internal data flow error. Additional debug info: gstbasesrc.c(1614): gst_base_src_loop (): /pipeline0/videotestsrc0: streaming task paused, reason not-negotiated (-4) */ /* ex:set ts=2 et: */ #ifndef __GST_BGSUBTRACTION_H__ #define __GST_BGSUBTRACTION_H__ #include #include #include #include #include G_BEGIN_DECLS #define GST_TYPE_BGSUBTRACTION (gst_bgsubtraction_get_type()) #define GST_BGSUBTRACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BGSUBTRACTION,GstBgSubtraction)) #define GST_BGSUBTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BGSUBTRACTION,GstBgSubtractionClass)) #define GST_IS_BGSUBTRACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BGSUBTRACTION)) #define GST_IS_BGSUBTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BGSUBTRACTION)) #define GST_TYPE_BGSUBTRACTION_OP (gst_bgsubtraction_op_get_type()) typedef struct _GstBgSubtraction GstBgSubtraction; typedef struct _GstBgSubtractionClass GstBgSubtractionClass; struct _GstBgSubtraction { GstBaseTransform parent; /*< private >*/ CvBGStatModel *model; IplImage *srcimage; IplImage *dstimage; /* gray levels */ CvSize size; int channels; int step; }; struct _GstBgSubtractionClass { GstBaseTransformClass parent_class; }; GType gst_bgsubtraction_get_type (void); G_END_DECLS #endif /* __GST_BGSUBTRACTION_H__ */ /* ex:set ts=2 et: */ #include "gstbgsubtraction.h" GST_DEBUG_CATEGORY_STATIC (gst_bgsubtraction_debug); #define GST_CAT_DEFAULT gst_bgsubtraction_debug static const GstElementDetails bgsubtraction_details = GST_ELEMENT_DETAILS ( "Background subtraction", "Filter/Vision", "Extracts the background from a video sequence", "Steve Frécinaux " ); static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/x-raw-gray") // GST_STATIC_CAPS ("video/x-raw-gray ; 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 ("video/x-raw-gray") ); enum { PROP_0 }; GST_BOILERPLATE (GstBgSubtraction, gst_bgsubtraction, GstBaseTransform, GST_TYPE_BASE_TRANSFORM); static void gst_bgsubtraction_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GstBgSubtraction *filter = GST_BGSUBTRACTION (object); switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gst_bgsubtraction_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GstBgSubtraction *filter = GST_BGSUBTRACTION (object); switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GstCaps * gst_bgsubtraction_transform_caps (GstBaseTransform *base, GstPadDirection direction, GstCaps *caps) { GstBgSubtraction *filter = GST_BGSUBTRACTION (base); GstCaps *tcaps; GstStructure *structure; int i, n; const GValue *width, *height, *framerate, *par; /* informations that should be conserved */ structure = gst_caps_get_structure (caps, 0); width = gst_structure_get_value (structure, "width"); height = gst_structure_get_value (structure, "height"); framerate = gst_structure_get_value (structure, "framerate"); par = gst_structure_get_value (structure, "pixel-aspect-ratio"); if (direction == GST_PAD_SINK) { tcaps = gst_static_pad_template_get_caps (&src_factory); } else if (direction == GST_PAD_SRC) { tcaps = gst_static_pad_template_get_caps (&sink_factory); } else { g_return_val_if_reached (NULL); } tcaps = gst_caps_make_writable (tcaps); n = gst_caps_get_size (tcaps); for (i = 0; i < n; i++) { structure = gst_caps_get_structure (tcaps, i); if (width != NULL) gst_structure_set_value (structure, "width", width); if (height != NULL) gst_structure_set_value (structure, "height", height); if (framerate != NULL) gst_structure_set_value (structure, "framerate", framerate); if (par != NULL) gst_structure_set_value (structure, "pixel-aspect-ratio", par); } // gst_caps_do_simplify (tcaps); return tcaps; } static gboolean gst_bgsubtraction_get_unit_size (GstBaseTransform *base, GstCaps *caps, guint *size) { GstBgSubtraction *filter = GST_BGSUBTRACTION (base); GstStructure *structure; gint width, height, bpp = 8; structure = gst_caps_get_structure (caps, 0); if (gst_structure_get_int (structure, "width", &width) && gst_structure_get_int (structure, "height", &height)) { *size = width * height; /* because the output image is gray-level */ return TRUE; } return FALSE; } static gboolean gst_bgsubtraction_set_caps (GstBaseTransform *base, GstCaps *incaps, GstCaps *outcaps) { GstBgSubtraction *filter = GST_BGSUBTRACTION (base); GstStructure *structure; int bpp = 8; gboolean ret; structure = gst_caps_get_structure (incaps, 0); /* Update the image header so it can contain the new image */ gst_structure_get_int (structure, "width", &(filter->size.width)); gst_structure_get_int (structure, "height", &(filter->size.height)); gst_structure_get_int (structure, "bpp", &bpp); filter->channels = bpp / 8; filter->step = filter->channels * filter->size.width; if (filter->srcimage != NULL) cvReleaseImageHeader (&(filter->srcimage)); filter->srcimage = cvCreateImageHeader (filter->size, IPL_DEPTH_8U, filter->channels); if (filter->dstimage != NULL) cvReleaseImageHeader (&(filter->dstimage)); filter->dstimage = cvCreateImageHeader (filter->size, IPL_DEPTH_8U, 1); if (filter->model != NULL) { cvReleaseBGStatModel (&(filter->model)); filter->model = NULL; } return TRUE; } static GstFlowReturn gst_bgsubtraction_transform (GstBaseTransform *base, GstBuffer *inbuf, GstBuffer *outbuf) { GstBgSubtraction *filter = GST_BGSUBTRACTION (base); gst_buffer_stamp (outbuf, inbuf); cvSetData (filter->srcimage, GST_BUFFER_DATA (inbuf), filter->step); cvSetData (filter->dstimage, GST_BUFFER_DATA (outbuf), filter->size.width); if (filter->model == NULL) { /* initialize the model with the first frame (ie the current one) */ filter->model = cvCreateGaussianBGModel (filter->srcimage, NULL); } else { /* update the current model */ cvUpdateBGStatModel (filter->srcimage, filter->model); } cvCopy (filter->model->foreground, filter->dstimage, NULL); return GST_FLOW_OK; } static void gst_bgsubtraction_init (GstBgSubtraction *filter, GstBgSubtractionClass *klass) { filter->model = NULL; filter->step = 0; filter->srcimage = NULL; filter->dstimage = NULL; } static void gst_bgsubtraction_finalize (GObject *object) { GstBgSubtraction *filter = GST_BGSUBTRACTION (object); if (filter->srcimage != NULL) cvReleaseImageHeader (&(filter->srcimage)); if (filter->dstimage != NULL) cvReleaseImageHeader (&(filter->dstimage)); if (filter->model != NULL) cvReleaseBGStatModel (&(filter->model)); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gst_bgsubtraction_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_factory)); gst_element_class_set_details (element_class, &bgsubtraction_details); } static void gst_bgsubtraction_class_init (GstBgSubtractionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstBaseTransformClass *transform_class = GST_BASE_TRANSFORM_CLASS (klass); object_class->set_property = gst_bgsubtraction_set_property; object_class->get_property = gst_bgsubtraction_get_property; object_class->finalize = gst_bgsubtraction_finalize; #if 1 transform_class->transform_caps = GST_DEBUG_FUNCPTR (gst_bgsubtraction_transform_caps); #endif transform_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_bgsubtraction_get_unit_size); transform_class->set_caps = GST_DEBUG_FUNCPTR (gst_bgsubtraction_set_caps); transform_class->transform = GST_DEBUG_FUNCPTR (gst_bgsubtraction_transform); GST_DEBUG_CATEGORY_INIT (gst_bgsubtraction_debug, "bgsubtraction", 0, "Background Subtraction"); }