diff --git a/ext/pylon/gstpylon.cpp b/ext/pylon/gstpylon.cpp index 1fa4d31..08061e5 100644 --- a/ext/pylon/gstpylon.cpp +++ b/ext/pylon/gstpylon.cpp @@ -52,6 +52,7 @@ #include "gstpylonsysmembufferfactory.h" #include +#include /* retry open camera limits in case of collision with other * process @@ -862,6 +863,65 @@ gboolean gst_pylon_set_configuration(GstPylon *self, const GstCaps *conf, height.SetValue(gst_height, Pylon::IntegerValueCorrection_None); GST_INFO("Set Feature Height: %d", gst_height); + /* set the cached offsetx/y values + * respect the rounding value adjustment rules + * -> offset will be adjusted to keep dimensions + */ + + GstPylonObjectPrivate *cam_properties = + (GstPylonObjectPrivate *)gst_pylon_object_get_instance_private( + reinterpret_cast(self->gcamera)); + + auto &offsetx_cache = cam_properties->dimension_cache.offsetx; + auto &offsety_cache = cam_properties->dimension_cache.offsety; + auto enable_correction = cam_properties->enable_correction; + + bool value_corrected = false; + if (offsetx_cache >= 0) { + Pylon::CIntegerParameter offsetx(nodemap, "OffsetX"); + if (enable_correction) { + try { + offsetx.SetValue( + offsetx_cache, + Pylon::EIntegerValueCorrection::IntegerValueCorrection_None); + } catch (GenICam::OutOfRangeException &) { + offsetx.SetValue( + offsetx_cache, + Pylon::EIntegerValueCorrection::IntegerValueCorrection_Nearest); + value_corrected = true; + } + } else { + offsetx.SetValue(offsetx_cache); + } + GST_INFO("Set Feature OffsetX: %d %s", + static_cast(offsetx.GetValue()), + value_corrected ? " [corrected]" : ""); + offsetx_cache = -1; + } + + value_corrected = false; + if (offsety_cache >= 0) { + Pylon::CIntegerParameter offsety(nodemap, "OffsetY"); + if (enable_correction) { + try { + offsety.SetValue( + offsety_cache, + Pylon::EIntegerValueCorrection::IntegerValueCorrection_None); + } catch (GenICam::OutOfRangeException &) { + offsety.SetValue( + offsety_cache, + Pylon::EIntegerValueCorrection::IntegerValueCorrection_Nearest); + value_corrected = true; + } + } else { + offsety.SetValue(offsety_cache); + } + GST_INFO("Set Feature Offsety: %d %s", + static_cast(offsety.GetValue()), + value_corrected ? " [corrected]" : ""); + offsety_cache = -1; + } + Pylon::CBooleanParameter framerate_enable(nodemap, "AcquisitionFrameRateEnable"); @@ -878,7 +938,6 @@ gboolean gst_pylon_set_configuration(GstPylon *self, const GstCaps *conf, framerate.TrySetValue(div, Pylon::FloatValueCorrection_None); GST_INFO("Set Feature AcquisitionFrameRateAbs: %f", div); } - } catch (const Pylon::GenericException &e) { g_set_error(err, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_FAILED, "%s", e.GetDescription()); diff --git a/gst-libs/gst/pylon/gstpylonobject.cpp b/gst-libs/gst/pylon/gstpylonobject.cpp index 44fcf31..d13aa87 100644 --- a/gst-libs/gst/pylon/gstpylonobject.cpp +++ b/gst-libs/gst/pylon/gstpylonobject.cpp @@ -41,20 +41,6 @@ #include -typedef struct _GstPylonObjectPrivate GstPylonObjectPrivate; -struct _GstPylonObjectPrivate { - std::shared_ptr camera; - GenApi::INodeMap* nodemap; - gboolean enable_correction; -}; - -typedef struct _GstPylonObjectDeviceMembers GstPylonObjectDeviceMembers; -struct _GstPylonObjectDeviceMembers { - const std::string& device_name; - GstPylonCache& feature_cache; - GenApi::INodeMap& nodemap; -}; - /************************************************************ * Start of GObject definition ***********************************************************/ @@ -71,10 +57,6 @@ static void gst_pylon_object_class_intern_init( g_type_class_adjust_private_offset(klass, &GstPylonObject_private_offset); gst_pylon_object_class_init((GstPylonObjectClass*)klass, device_members); } -static inline gpointer gst_pylon_object_get_instance_private( - GstPylonObject* self) { - return (G_STRUCT_MEMBER_P(self, GstPylonObject_private_offset)); -} GType gst_pylon_object_register(const std::string& device_name, GstPylonCache& feature_cache, @@ -114,6 +96,10 @@ GType gst_pylon_object_register(const std::string& device_name, * End of GObject definition ***********************************************************/ +gpointer gst_pylon_object_get_instance_private(GstPylonObject* self) { + return (G_STRUCT_MEMBER_P(self, GstPylonObject_private_offset)); +} + /* prototypes */ static void gst_pylon_object_install_properties(GstPylonObjectClass* klass, GenApi::INodeMap& nodemap, @@ -389,6 +375,36 @@ static void gst_pylon_object_set_property(GObject* object, guint property_id, selector_data = gst_pylon_param_spec_selector_get_data(pspec); } + /* check if property is from dimension list + * and set before streaming + */ + if (!priv->camera->IsGrabbing()) { + bool is_cached = false; + if (std::string(pspec->name) == "OffsetX") { + priv->dimension_cache.offsetx = g_value_get_int64(value); + is_cached = true; + } else if (std::string(pspec->name) == "OffsetY") { + priv->dimension_cache.offsety = g_value_get_int64(value); + is_cached = true; + } else if (std::string(pspec->name) == "Width") { + priv->dimension_cache.width = g_value_get_int64(value); + is_cached = true; + } else if (std::string(pspec->name) == "Height") { + priv->dimension_cache.height = g_value_get_int64(value); + is_cached = true; + } + if (is_cached) { + GST_INFO("Caching property \"%s\". Value is checked during caps fixation", + pspec->name); + + /* skip to set the camera property value + * any value in the gst property range of this feature is accepted in this + * phase + */ + return; + } + } + try { switch (value_type) { case G_TYPE_INT64: @@ -436,6 +452,39 @@ static void gst_pylon_object_get_property(GObject* object, guint property_id, selector_data = gst_pylon_param_spec_selector_get_data(pspec); } + /* check if property is from dimension list + * and get from cache if not streaming + */ + if (!priv->camera->IsGrabbing()) { + bool is_cached = false; + if (std::string(pspec->name) == "OffsetX" && + priv->dimension_cache.offsetx >= 0) { + is_cached = true; + g_value_set_int64(value, priv->dimension_cache.offsetx); + } else if (std::string(pspec->name) == "OffsetY" && + priv->dimension_cache.offsety >= 0) { + is_cached = true; + g_value_set_int64(value, priv->dimension_cache.offsety); + } else if (std::string(pspec->name) == "Width" && + priv->dimension_cache.width >= 0) { + is_cached = true; + g_value_set_int64(value, priv->dimension_cache.width); + } else if (std::string(pspec->name) == "Height" && + priv->dimension_cache.height >= 0) { + is_cached = true; + g_value_set_int64(value, priv->dimension_cache.height); + } + + if (is_cached) { + GST_INFO( + "Read cached property \"%s\". Value might be adjusted during caps " + "fixation", + pspec->name); + + return; + } + } + try { switch (g_type_fundamental(pspec->value_type)) { case G_TYPE_INT64: @@ -499,6 +548,11 @@ GObject* gst_pylon_object_new( priv->nodemap = nodemap; priv->enable_correction = enable_correction; + /* setup dimension cache + * -1 -> not activly set + */ + priv->dimension_cache = {-1, -1, -1, -1}; + return obj; } diff --git a/gst-libs/gst/pylon/gstpylonobject.h b/gst-libs/gst/pylon/gstpylonobject.h index 74a46d5..1fcf893 100644 --- a/gst-libs/gst/pylon/gstpylonobject.h +++ b/gst-libs/gst/pylon/gstpylonobject.h @@ -44,6 +44,26 @@ struct _GstPylonObjectClass { GstObjectClass parent_class; }; +typedef struct { + gint width; + gint height; + gint offsetx; + gint offsety; +} dimension_t; + +typedef struct { + std::shared_ptr camera; + GenApi::INodeMap* nodemap; + gboolean enable_correction; + dimension_t dimension_cache; +} GstPylonObjectPrivate; + +typedef struct { + const std::string& device_name; + GstPylonCache& feature_cache; + GenApi::INodeMap& nodemap; +} GstPylonObjectDeviceMembers; + EXT_PYLONSRC_API GType gst_pylon_object_register(const std::string& device_name, GstPylonCache& feature_cache, GenApi::INodeMap& nodemap); @@ -52,8 +72,11 @@ EXT_PYLONSRC_API GObject* gst_pylon_object_new( const std::string& device_name, GenApi::INodeMap* nodemap, gboolean enable_correction); -void gst_pylon_object_set_pylon_selector(GenApi::INodeMap& nodemap, - const gchar* selector_name, - gint64& selector_value); +EXT_PYLONSRC_API void gst_pylon_object_set_pylon_selector( + GenApi::INodeMap& nodemap, const gchar* selector_name, + gint64& selector_value); + +EXT_PYLONSRC_API gpointer +gst_pylon_object_get_instance_private(GstPylonObject* self); #endif