From 6baedb9ad654f0308d06931456fd4bd334780069 Mon Sep 17 00:00:00 2001 From: Thies Moeller Date: Mon, 8 May 2023 09:06:11 +0200 Subject: [PATCH 1/5] terminate pylon libraries on pylonsrc finalization --- ext/pylon/gstpylon.cpp | 5 ++++- ext/pylon/gstpylon.h | 2 ++ ext/pylon/gstpylonsrc.cpp | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/pylon/gstpylon.cpp b/ext/pylon/gstpylon.cpp index 796e7d2..1fa4d31 100644 --- a/ext/pylon/gstpylon.cpp +++ b/ext/pylon/gstpylon.cpp @@ -148,6 +148,8 @@ static const std::vector gst_structure_formats = { void gst_pylon_initialize() { Pylon::PylonInitialize(); } +void gst_pylon_terminate() { Pylon::PylonTerminate(); } + static std::string gst_pylon_get_camera_fullname( Pylon::CBaslerUniversalInstantCamera &camera) { return std::string(camera.GetDeviceInfo().GetFullName()); @@ -890,7 +892,8 @@ gboolean gst_pylon_set_configuration(GstPylon *self, const GstCaps *conf, #ifdef NVMM_ENABLED GstCapsFeatures *features = gst_caps_get_features(conf, 0); if (gst_caps_features_contains(features, "memory:NVMM")) { - self->buffer_factory = std::make_unique(self->nvsurface_layout, self->gpu_id); + self->buffer_factory = std::make_unique( + self->nvsurface_layout, self->gpu_id); self->buffer_factory->SetConfig(conf); self->mem_type = MEM_NVMM; diff --git a/ext/pylon/gstpylon.h b/ext/pylon/gstpylon.h index 170a0f3..d89cb3a 100644 --- a/ext/pylon/gstpylon.h +++ b/ext/pylon/gstpylon.h @@ -63,6 +63,8 @@ gboolean gst_pylon_set_user_config(GstPylon *self, const gchar *user_set, GError **err); void gst_pylon_free(GstPylon *self); +void gst_pylon_terminate(); + gboolean gst_pylon_start(GstPylon *self, GError **err); gboolean gst_pylon_stop(GstPylon *self, GError **err); void gst_pylon_interrupt_capture(GstPylon *self); diff --git a/ext/pylon/gstpylonsrc.cpp b/ext/pylon/gstpylonsrc.cpp index 29ca132..0b6face 100644 --- a/ext/pylon/gstpylonsrc.cpp +++ b/ext/pylon/gstpylonsrc.cpp @@ -541,6 +541,8 @@ static void gst_pylon_src_finalize(GObject *object) { self->stream = NULL; } + gst_pylon_terminate(); + G_OBJECT_CLASS(gst_pylon_src_parent_class)->finalize(object); } From 29178fb4dd1b1d04730c78d6c56da0520921b2f0 Mon Sep 17 00:00:00 2001 From: Thies Moeller Date: Wed, 3 May 2023 16:57:04 +0200 Subject: [PATCH 2/5] add support for pylon 7.3 --- .github/workflows/ci.yml | 21 ++++++++++++--------- README.md | 12 ++++++------ gst-libs/gst/pylon/meson.build | 5 +++-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b63b4f3..aad6224 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,12 +21,15 @@ jobs: - name: Installer list run: | tee pylon-installer.txt <<"EOF" + ${PYLON_DOWNLOAD_URL_BASE}/pylon_7.3.0.27189_linux-x86_64_setup.tar.gz ${PYLON_DOWNLOAD_URL_BASE}/pylon_7.2.1.25747_x86_64_setup.tar.gz ${PYLON_DOWNLOAD_URL_BASE}/pylon_7.1.0.25066_x86_64_setup.tar.gz ${PYLON_DOWNLOAD_URL_BASE}/pylon_6.3.0.23157_x86_64_setup.tar.gz + ${PYLON_DOWNLOAD_URL_BASE}/pylon_7.3.0.27189_linux-aarch64_setup.tar.gz ${PYLON_DOWNLOAD_URL_BASE}/pylon_7.2.1.25747_aarch64_setup.tar.gz ${PYLON_DOWNLOAD_URL_BASE}/pylon_7.1.0.25066_aarch64_setup.tar.gz ${PYLON_DOWNLOAD_URL_BASE_62}/pylon_6.2.0.21487_aarch64_setup.tar.gz + ${PYLON_DOWNLOAD_URL_BASE}/Basler_pylon_7.3.0.27189.exe ${PYLON_DOWNLOAD_URL_BASE}/Basler_pylon_7.2.1.25747.exe ${PYLON_DOWNLOAD_URL_BASE}/Basler_pylon_7.1.0.25066.exe ${PYLON_DOWNLOAD_URL_BASE}/pylon-6.2.0.21487.dmg @@ -62,10 +65,10 @@ jobs: strategy: matrix: os: [windows-latest] - py_version: [7.2.1.25747, 7.1.0.25066 ] + py_version: [7.3.0.27189, 7.2.1.25747, 7.1.0.25066 ] fail-fast: false runs-on: ${{ matrix.os }} - name: Build pylon ${{ matrix.py_version }} on ${{ matrix.os }}-x86_64 + name: Build pylon ${{ matrix.py_version }} on ${{ matrix.os }} steps: - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 @@ -115,7 +118,7 @@ jobs: strategy: matrix: os: [ubuntu18.04, ubuntu20.04, ubuntu22.04] - py_version: [7.2.1.25747, 7.1.0.25066, 6.2.0.21487 ] + py_version: [7.3.0.27189_linux-aarch64, 7.2.1.25747_aarch64, 7.1.0.25066_aarch64, 6.2.0.21487_aarch64 ] fail-fast: false runs-on: ubuntu-latest name: Build pylon ${{ matrix.py_version }} on ${{ matrix.os }}-aarch64 @@ -141,12 +144,12 @@ jobs: uname -a # install pylon - PYLON_TGZ=$(readlink -m /pylon-installer/pylon_${{ matrix.py_version }}_aarch64_setup.tar.gz) + PYLON_TGZ=$(readlink -m /pylon-installer/pylon_${{ matrix.py_version }}_setup.tar.gz) mkdir pylon_tmp pushd pylon_tmp tar -xf $PYLON_TGZ mkdir -p /opt/pylon - tar -C /opt/pylon -xzf pylon_${{ matrix.py_version }}_aarch64.tar.gz + tar -C /opt/pylon -xzf pylon?${{ matrix.py_version }}.tar.gz popd # install required environment @@ -195,10 +198,10 @@ jobs: strategy: matrix: os: [ubuntu-20.04, ubuntu-22.04] - py_version: [7.2.1.25747, 7.1.0.25066, 6.3.0.23157 ] + py_version: [7.3.0.27189_linux-x86_64, 7.2.1.25747_x86_64, 7.1.0.25066_x86_64, 6.3.0.23157_x86_64 ] fail-fast: false runs-on: ${{ matrix.os }} - name: Build pylon ${{ matrix.py_version }} on ${{ matrix.os }}-x64 + name: Build pylon ${{ matrix.py_version }} on ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -209,12 +212,12 @@ jobs: - name: install pylon run: | - PYLON_TGZ=$(readlink -m pylon-installer/pylon_${{ matrix.py_version }}_x86_64_setup.tar.gz) + PYLON_TGZ=$(readlink -m pylon-installer/pylon_${{ matrix.py_version }}_setup.tar.gz) mkdir pylon_tmp pushd pylon_tmp tar -xf $PYLON_TGZ sudo mkdir -p /opt/pylon - sudo tar -C /opt/pylon -xzf pylon_${{ matrix.py_version }}_x86_64.tar.gz + sudo tar -C /opt/pylon -xzf pylon?${{ matrix.py_version }}.tar.gz popd - name: install required environment diff --git a/README.md b/README.md index 24af45c..e003d7f 100644 --- a/README.md +++ b/README.md @@ -318,12 +318,12 @@ As a first step install Basler pylon according to your platform. Downloads are a The supported pylon versions on the different platforms are: -| | 7.2 | 7.1 | 6.2 | -|-----------------|:----:|:----:|:----:| -| Windows x86_64 | x | x | | -| Linux x86_64 | x | x | | -| Linux aarch64 | x | x | x | -| macOS x86_64 | - | | +| | 7.3 | 7.2 | 7.1 | 6.2 | +|-----------------|:----:|:----:|:----:|:----:| +| Windows x86_64 | x | x | x | | +| Linux x86_64 | x | x | x | | +| Linux aarch64 | x | x | x | x | +| macOS x86_64 | - | - | - | > macOS build not available for now due to current meson/cmake interaction issues diff --git a/gst-libs/gst/pylon/meson.build b/gst-libs/gst/pylon/meson.build index 91f4616..59dd5bb 100644 --- a/gst-libs/gst/pylon/meson.build +++ b/gst-libs/gst/pylon/meson.build @@ -11,8 +11,9 @@ if target_machine.system() == 'linux' and pylon_path == 'PYLON_ROOT_NOT_SET' endif # detect pylon 7.x -pylon_dep = dependency('pylon', method : 'cmake', modules : ['pylon::PylonBase', 'pylon::GCBase', 'pylon::GenApi', 'pylon::PylonUtility'], - version : '>=7.1', cmake_module_path: pylon_path / 'share/pylon/cmake/' , required: false) +pylon_dep = dependency('pylon', method : 'cmake', modules : ['pylon::pylon'], + version : '>=7.1', cmake_args : [ '-DCMAKE_PREFIX_PATH=' + pylon_path / 'share/pylon/cmake/', '-DPYLON_ROOT=' + pylon_path ] , required: false) + if pylon_dep.found() # patch rpath on linux if target_machine.system() == 'linux' From 5de4664513a779f7a4c42ac818f55208d4a43fb8 Mon Sep 17 00:00:00 2001 From: Thies Moeller Date: Wed, 3 May 2023 13:16:14 +0200 Subject: [PATCH 3/5] cache dimension settings in PAUSED state Allow to set offsetx/y early in construction. Move the validation of offset vs width/height to set_configuration --- ext/pylon/gstpylon.cpp | 61 +++++++++++++++++- gst-libs/gst/pylon/gstpylonobject.cpp | 90 +++++++++++++++++++++------ gst-libs/gst/pylon/gstpylonobject.h | 29 ++++++++- 3 files changed, 158 insertions(+), 22 deletions(-) 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 From 73138bd1c45694bec949d4a1accf4452574499fd Mon Sep 17 00:00:00 2001 From: Thies Moeller Date: Mon, 8 May 2023 10:22:07 +0200 Subject: [PATCH 4/5] update to 0.7.0 --- CHANGELOG.md | 19 +++++++++++++++++++ README.md | 36 +++++++++++++++++++----------------- meson.build | 2 +- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f79772..9dc1760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ # Changelog All notable changes to this project will be documented in this file. +## [0.7.0] - 2023-05-08 + +### Changed +- offset x/y are cached when pipeline is not playing. + * setting the offset an ROI configured via caps is possible now + * fixes #44 + +### Added +- Restructing of buffer pool management to support platform specific optimal buffer types +- NVMM support + * This feature is automatically enabled when both the CUDA library and the DeepStream library are installed on the system. + * If enabled pylonsrc can directly generate output buffers into nvmm, that can be used by other nvidia elements. + * Current restrictions: + * only runs on NVIDIA Jetson at the moment + +- Pylon 7.3 + * meson supports to build the plugin with pylon 7.3 now + + ## [0.6.2] - 2023-04-04 ### Changed diff --git a/README.md b/README.md index e003d7f..3cd79e7 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,25 @@ possible values) after applying the userset and pfs file. It is recommended to set a caps-filter to explicitly set the wanted capabilities. +# NVMM Support + + +NVMM caps are now supported in the current version of the element. This feature +is automatically enabled when both the CUDA library and the DeepStream library +are installed on the system. + +By using this support, a memory speedup can be achieved as it eliminates the +need for an additional element to connect the system memory and NVIDIA's GPU +memory. + +Here's an example of how to use this feature: + +```bash +gst-launch-1.0 pylonsrc ! "video/x-raw(memory:NVMM), width=1920, height=1080" ! nvvidconv ! "video/x-raw(memory:NVMM), width=1280, height=720" ! fakesink +``` + + + ### Handle capture errors `pylonsrc` lets you decide what to do when a capture error happens. @@ -533,23 +552,6 @@ Installation on macOS is currently not supported due to conflicts between meson This target will be integrated after a Basler pylon 7.x release for macOS -# NVMM Support - - -NVMM caps are now supported in the current version of the element. This feature -is automatically enabled when both the CUDA library and the DeepStream library -are installed on the system. - -By using this support, a memory speedup can be achieved as it eliminates the -need for an additional element to connect the system memory and NVIDIA's GPU -memory. - -Here's an example of how to use this feature: - -```bash -gst-launch-1.0 pylonsrc ! "video/x-raw(memory:NVMM), width=1920, height=1080" ! nvvidconv ! "video/x-raw(memory:NVMM), width=1280, height=720" ! fakesink -``` - # Known issues diff --git a/meson.build b/meson.build index ae98e8a..81f2894 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('gst-plugin-pylon', 'c', 'cpp', - version : '0.6.2', + version : '0.7.0', meson_version : '>= 0.61', default_options : [ 'warning_level=1', 'buildtype=debugoptimized' ]) From 1e70e48c39e13cf0c74d995fe2f745bcb85d0f19 Mon Sep 17 00:00:00 2001 From: Thies Moeller Date: Wed, 10 May 2023 09:24:44 +0200 Subject: [PATCH 5/5] fix case where PYLON_ROOT is defined to wrong location --- gst-libs/gst/pylon/meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/pylon/meson.build b/gst-libs/gst/pylon/meson.build index 59dd5bb..b2473e8 100644 --- a/gst-libs/gst/pylon/meson.build +++ b/gst-libs/gst/pylon/meson.build @@ -5,7 +5,9 @@ # import PYLON_ROOT environment into meson pylon_path = run_command(python3, '-c', 'import os; print(os.environ.get("PYLON_ROOT","PYLON_ROOT_NOT_SET"))', check: false).stdout().strip() -if target_machine.system() == 'linux' and pylon_path == 'PYLON_ROOT_NOT_SET' +fs = import('fs') + +if target_machine.system() == 'linux' and (pylon_path == 'PYLON_ROOT_NOT_SET' or not fs.exists(pylon_path / 'include/pylon')) # PYLON_ROOT has to be set error('PYLON_ROOT has to be set to location of pylon install e.g. /opt/pylon') endif