From af25506097abd284e1391799df9cc2ba1b6f4fb1 Mon Sep 17 00:00:00 2001 From: "Joshua M. Doe" Date: Wed, 21 Apr 2010 07:22:11 -0400 Subject: [PATCH] niimaqsrc: Fix caps negotiation Set caps to src pad during GstBaseSrc.start. Use static pad templates instead of dynamically generating caps. Force bpp to 16 even if IMAQ says 10, 12, 14 (to be fixed in the future by implementing GstBaseSrc.negotiate). --- sys/gstniimaq.c | 142 ++++++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 60 deletions(-) diff --git a/sys/gstniimaq.c b/sys/gstniimaq.c index 6141159..7a58332 100644 --- a/sys/gstniimaq.c +++ b/sys/gstniimaq.c @@ -65,6 +65,27 @@ enum #define DEFAULT_PROP_TIMESTAMP_OFFSET 0 #define DEFAULT_PROP_BUFSIZE 10 +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ( + "video/x-raw-gray, " + "bpp = (int) 8, " + "depth = (int) 8, " + "width = (int) [ 1, max ], " + "height = (int) [ 1, max ], " + "framerate = (fraction) [ 0, max ]" + ";" + "video/x-raw-gray, " + "bpp = (int) {10, 12, 14, 16}, " + "depth = (int) 16, " + "endianness = (int) LITTLE_ENDIAN, " + "width = (int) [ 1, max ], " + "height = (int) [ 1, max ], " + "framerate = (fraction) [ 0, max ]" + ) +); + static void gst_niimaq_init_interfaces (GType type); GST_BOILERPLATE_FULL (GstNiImaq, gst_niimaq, GstPushSrc, @@ -80,7 +101,6 @@ static void gst_niimaq_get_property (GObject * object, guint prop_id, /* GstBaseSrc virtual methods */ static GstCaps *gst_niimaq_get_caps (GstBaseSrc * bsrc); static gboolean gst_niimaq_set_caps (GstBaseSrc * bsrc, GstCaps * caps); -static void gst_niimaq_src_fixate (GstPad * pad, GstCaps * caps); static void gst_niimaq_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, GstClockTime * start, GstClockTime * end); static gboolean gst_niimaq_start (GstBaseSrc * src); @@ -93,11 +113,10 @@ static GstFlowReturn gst_niimaq_create (GstPushSrc * psrc, GstBuffer ** buffer); static gboolean gst_niimaq_parse_caps (const GstCaps * caps, gint * width, gint * height, gint * depth, gint * bpp); -static gboolean gst_niimaq_set_caps_color (GstStructure * gs, int bpp, int depth); +static gboolean gst_niimaq_set_caps_color (GstStructure * gs, gint bpp, gint depth); static gboolean gst_niimaq_set_caps_framesize (GstStructure * gs, gint width, gint height); -static GstCaps *gst_niimaq_get_all_niimaq_caps (); static GstCaps *gst_niimaq_get_cam_caps (GstNiImaq * src); static void _____BEGIN_FUNCTIONS_____(); @@ -356,9 +375,7 @@ gst_niimaq_base_init (gpointer g_class) gst_element_class_set_details (element_class, &niimaq_details); gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - gst_niimaq_get_all_niimaq_caps ())); - + gst_static_pad_template_get (&src_factory)); } static void @@ -397,7 +414,6 @@ gst_niimaq_class_init (GstNiImaqClass * klass) gstbasesrc_class->get_caps = gst_niimaq_get_caps; gstbasesrc_class->set_caps = gst_niimaq_set_caps; - gstbasesrc_class->get_times = gst_niimaq_get_times; gstpushsrc_class->create = gst_niimaq_create; gstbasesrc_class->start = gst_niimaq_start; @@ -413,7 +429,7 @@ gst_niimaq_init (GstNiImaq * src, GstNiImaqClass * g_class) gst_pad_use_fixed_caps (srcpad); src->timestamp_offset = 0; - src->caps = gst_niimaq_get_all_niimaq_caps (); + src->caps = NULL; src->bufsize = 10; src->n_frames = 0; src->cumbufnum = 0; @@ -491,9 +507,9 @@ gst_niimaq_get_property (GObject * object, guint prop_id, GValue * value, static GstCaps * gst_niimaq_get_caps (GstBaseSrc * bsrc) { - GstNiImaq *gsrc; + GstNiImaq *gsrc = GST_NIIMAQ (bsrc); - gsrc = GST_NIIMAQ (bsrc); + GST_DEBUG_OBJECT (bsrc, "Entering function get_caps"); g_return_val_if_fail (gsrc->caps, NULL); @@ -512,14 +528,15 @@ gst_niimaq_set_caps (GstBaseSrc * bsrc, GstCaps * caps) niimaq = GST_NIIMAQ (bsrc); + GST_DEBUG_OBJECT (bsrc, "Entering function set_caps"); + GST_DEBUG_OBJECT (caps, "are the caps being set"); if (niimaq->caps) { gst_caps_unref (niimaq->caps); + niimaq->caps = gst_caps_copy (caps); } - niimaq->caps = gst_niimaq_get_cam_caps(niimaq); - res = gst_niimaq_parse_caps (niimaq->caps, &width, &height, &depth, &bpp); if (res) { @@ -672,7 +689,7 @@ gst_niimaq_parse_caps (const GstCaps * caps, gint * width, gint * height, /* Set color on caps */ static gboolean -gst_niimaq_set_caps_color (GstStructure * gs, int bpp, int depth) +gst_niimaq_set_caps_color (GstStructure * gs, gint bpp, gint depth) { gboolean ret = TRUE; @@ -682,8 +699,8 @@ gst_niimaq_set_caps_color (GstStructure * gs, int bpp, int depth) "depth", G_TYPE_INT, depth, NULL); if (depth > 8) { gst_structure_set(gs, - "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, - NULL); + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + NULL); } return ret; @@ -704,57 +721,27 @@ gst_niimaq_set_caps_framesize (GstStructure * gs, gint width, gint height) { gst_structure_set (gs, "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - NULL); + "height", G_TYPE_INT, height, + NULL); return TRUE; } -GstCaps * -gst_niimaq_get_all_niimaq_caps () -{ - /* - generate all possible caps - - */ - - GstCaps *gcaps; - GstStructure *gs; - gint i = 0; - - gcaps = gst_caps_new_empty (); - - gs = gst_structure_empty_new ("video"); - gst_structure_set_name (gs, "video/x-raw-gray"); - gst_structure_set (gs, - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "bpp", GST_TYPE_INT_RANGE, 10, 16, - "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - gst_caps_append_structure (gcaps, gs); - - gs = gst_structure_empty_new ("video"); - gst_structure_set_name (gs, "video/x-raw-gray"); - gst_structure_set (gs, - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "bpp", G_TYPE_INT, 8, - "depth", G_TYPE_INT, 8, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - gst_caps_append_structure (gcaps, gs); - - return gcaps; -} - +/** +* gst_niimaq_get_cam_caps: +* src: #GstNiImaq +* +* Get caps of camera attached to open IMAQ interface +* +* Returns: the #GstCaps of the src pad. Unref the caps when you no longer need it. +*/ GstCaps * gst_niimaq_get_cam_caps (GstNiImaq * src) { GstCaps *gcaps = NULL; Int32 rval; uInt32 val; - int width, height, depth, bpp; + gint width, height, depth, bpp; GstStructure *gs; gcaps = gst_caps_new_empty (); @@ -774,6 +761,9 @@ gst_niimaq_get_cam_caps (GstNiImaq * src) rval &= imgGetAttribute(src->iid, IMG_ATTR_ROI_HEIGHT, &val); height = val; + /* TODO: support both actual bpp and bpp=16 */ + bpp = depth; + if (rval) { GST_ELEMENT_ERROR (src, STREAM, FAILED, ("attempt to read attributes failed"), @@ -790,9 +780,19 @@ gst_niimaq_get_cam_caps (GstNiImaq * src) goto error; } - gst_structure_set(gs, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + /* hard code framerate to 30Hz as IMAQ doesn't tell us anything about it */ + gst_structure_set(gs, "framerate", GST_TYPE_FRACTION, 30, 1, NULL); - gst_caps_append_structure (gcaps, gs); + gst_caps_append_structure (gcaps, gst_structure_copy (gs)); + + /* if (8 < bpp < 16), then append structure with bpp=16 so ffmpegcolorspace + * and other elements can work directly with this src */ + /* TODO: support both actual bpp (10,12,14) and 16 */ + /*if (bpp > 8) { + gst_niimaq_set_caps_color (gs, 16, 16); + gst_caps_append_structure (gcaps, gst_structure_copy (gs)); + }*/ + gst_object_unref (gs); GST_DEBUG_OBJECT (gcaps, "are the camera caps"); @@ -812,7 +812,9 @@ gst_niimaq_start (GstBaseSrc * src) { GstNiImaq* filter = GST_NIIMAQ(src); Int32 rval; - int i; + gboolean ret; + gint i; + GstPad * pad; GST_LOG_OBJECT (filter, "Opening IMAQ interface: %s", filter->interface_name); @@ -836,6 +838,26 @@ gst_niimaq_start (GstBaseSrc * src) goto error; } + /* get caps from camera and set to src pad*/ + if (filter->caps) { + gst_caps_unref (filter->caps); + filter->caps = NULL; + } + filter->caps = gst_niimaq_get_cam_caps (filter); + if (filter->caps == NULL) { + GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, ("Failed to get caps from IMAQ"), + ("Failed to get caps from IMAQ")); + goto error; + } + pad = gst_element_get_static_pad (GST_ELEMENT (src), "src"); + ret = gst_pad_set_caps (pad, gst_caps_copy (filter->caps)); + gst_object_unref (pad); + if (!ret) { + GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, ("Failed set caps to src pad"), + ("Failed set caps to src pad")); + goto error; + } + GST_LOG_OBJECT (filter, "Creating ring with %d buffers", filter->bufsize); filter->buflist = g_new(guint32*, filter->bufsize); @@ -934,4 +956,4 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "niimaq", "NI-IMAQ Video Source", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) \ No newline at end of file