gentlsrc: add producer property to select between EVT and Basler

This is still a bandaid fix until we properly parse the XML files
This commit is contained in:
Joshua M. Doe 2021-05-26 10:32:13 -04:00
parent 765662aa82
commit 8e34238034
2 changed files with 137 additions and 37 deletions

View File

@ -60,29 +60,61 @@
// "C:\\BitFlow SDK 6.20\\Bin64\\BFGTL.cti"; // "C:\\BitFlow SDK 6.20\\Bin64\\BFGTL.cti";
// "C:\\Program Files\\Basler\\pylon 5\\Runtime\\x64\\ProducerGEV.cti"; // "C:\\Program Files\\Basler\\pylon 5\\Runtime\\x64\\ProducerGEV.cti";
// EVT static void
#define GENAPI_WIDTH 0xA000 initialize_evt_addresses (GstGenTlProducer * producer)
#define GENAPI_HEIGHT 0xA004 {
#define GENAPI_PIXFMT 0xA008 memset (producer, 0, sizeof (producer));
#define GENAPI_PAYLOAD_SIZE 0xD008 producer->cti_path =
#define GENAPI_ACQMODE 0xB000 g_strdup ("C:\\Program Files\\EVT\\eSDK\\bin\\EmergentGenTL.cti");
#define GENAPI_ACQSTART 0xB004 producer->acquisition_mode_value = 0;
#define GENAPI_ACQSTOP 0xB008 producer->width = 0xA000;
#define GENAPI_TICK_FREQ_LOW 0x0940 producer->height = 0xA004;
#define GENAPI_TICK_FREQ_HIGH 0x093C producer->pixel_format = 0xA008;
#define GENAPI_TIMESTAMP_CONTROL_LATCH 0x944 producer->payload_size = 0xD008;
#define GENAPI_TIMESTAMP_VALUE_LOW 0x094C producer->acquisition_mode = 0xB000;
#define GENAPI_TIMESTAMP_VALUE_HIGH 0x0948 producer->acquisition_start = 0xB004;
#define CTI_PATH "C:\\Program Files\\EVT\\eSDK\\bin\\EmergentGenTL.cti" producer->acquisition_stop = 0xB008;
producer->tick_frequency_low = 0x0940;
producer->tick_frequency_high = 0x093C;
producer->timestamp_control_latch = 0x944;
producer->timestamp_low = 0x094C;
producer->timestamp_high = 0x0948;
}
// Basler static void
//#define GENAPI_WIDTH 0x30204 initialize_basler_addresses (GstGenTlProducer * producer)
//#define GENAPI_HEIGHT 0x30224 {
//#define GENAPI_PAYLOAD_SIZE 0x10088 memset (producer, 0, sizeof (producer));
//#define GENAPI_ACQMODE 0x40004 producer->cti_path =
//#define GENAPI_ACQSTART 0x40024 g_strdup
//#define GENAPI_ACQSTOP 0x40044 ("C:\\Program Files\\Basler\\pylon 5\\Runtime\\x64\\ProducerGEV.cti");
//#define CTI_PATH "C:\\Program Files\\Basler\\pylon 6\\Runtime\\x64\\ProducerGEV.cti" producer->acquisition_mode_value = 2;
producer->width = 0x30204;
producer->height = 0x30224;
producer->pixel_format = 0x30024;
producer->payload_size = 0x10088;
producer->acquisition_mode = 0x40004;
producer->acquisition_start = 0x40024;
producer->acquisition_stop = 0x40044;
}
#define GST_TYPE_GENTLSRC_PRODUCER (gst_gentlsrc_producer_get_type())
static GType
gst_gentlsrc_producer_get_type (void)
{
static GType gentlsrc_producer_type = 0;
static const GEnumValue gentlsrc_producer[] = {
{GST_GENTLSRC_PRODUCER_BASLER, "Basler producer", "basler"},
{GST_GENTLSRC_PRODUCER_EVT, "EVT producer", "evt"},
{0, NULL, NULL},
};
if (!gentlsrc_producer_type) {
gentlsrc_producer_type =
g_enum_register_static ("GstGenTlSrcProducer", gentlsrc_producer);
}
return gentlsrc_producer_type;
}
GST_DEBUG_CATEGORY_STATIC (gst_gentlsrc_debug); GST_DEBUG_CATEGORY_STATIC (gst_gentlsrc_debug);
#define GST_CAT_DEFAULT gst_gentlsrc_debug #define GST_CAT_DEFAULT gst_gentlsrc_debug
@ -109,6 +141,7 @@ static gchar *gst_gentlsrc_get_error_string (GstGenTlSrc * src);
enum enum
{ {
PROP_0, PROP_0,
PROP_PRODUCER,
PROP_INTERFACE_INDEX, PROP_INTERFACE_INDEX,
PROP_INTERFACE_ID, PROP_INTERFACE_ID,
PROP_DEVICE_INDEX, PROP_DEVICE_INDEX,
@ -119,6 +152,7 @@ enum
PROP_TIMEOUT PROP_TIMEOUT
}; };
#define DEFAULT_PROP_PRODUCER GST_GENTLSRC_PRODUCER_BASLER
#define DEFAULT_PROP_INTERFACE_INDEX 0 #define DEFAULT_PROP_INTERFACE_INDEX 0
#define DEFAULT_PROP_INTERFACE_ID "" #define DEFAULT_PROP_INTERFACE_ID ""
#define DEFAULT_PROP_DEVICE_INDEX 0 #define DEFAULT_PROP_DEVICE_INDEX 0
@ -206,7 +240,7 @@ gboolean
gst_gentlsrc_bind_functions (GstGenTlSrc * src) gst_gentlsrc_bind_functions (GstGenTlSrc * src)
{ {
GModule *module; GModule *module;
const char cti_path[] = CTI_PATH; const char *cti_path = src->producer.cti_path;
gboolean ret = TRUE; gboolean ret = TRUE;
GST_DEBUG_OBJECT (src, "Trying to bind functions from '%s'", cti_path); GST_DEBUG_OBJECT (src, "Trying to bind functions from '%s'", cti_path);
@ -311,6 +345,12 @@ gst_gentlsrc_class_init (GstGenTlSrcClass * klass)
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_gentlsrc_create); gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_gentlsrc_create);
/* Install GObject properties */ /* Install GObject properties */
g_object_class_install_property (gobject_class, PROP_PRODUCER,
g_param_spec_enum ("producer", "Producer", "GenTL producer",
GST_TYPE_GENTLSRC_PRODUCER, DEFAULT_PROP_PRODUCER,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
GST_PARAM_MUTABLE_PLAYING));
g_object_class_install_property (gobject_class, PROP_INTERFACE_INDEX, g_object_class_install_property (gobject_class, PROP_INTERFACE_INDEX,
g_param_spec_uint ("interface-index", "Interface index", g_param_spec_uint ("interface-index", "Interface index",
"Interface index number, zero-based, overridden by interface-id", "Interface index number, zero-based, overridden by interface-id",
@ -386,6 +426,7 @@ gst_gentlsrc_init (GstGenTlSrc * src)
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
/* initialize member variables */ /* initialize member variables */
src->producer_prop = DEFAULT_PROP_PRODUCER;
src->interface_index = DEFAULT_PROP_INTERFACE_INDEX; src->interface_index = DEFAULT_PROP_INTERFACE_INDEX;
src->interface_id = g_strdup (DEFAULT_PROP_INTERFACE_ID); src->interface_id = g_strdup (DEFAULT_PROP_INTERFACE_ID);
src->num_capture_buffers = DEFAULT_PROP_NUM_CAPTURE_BUFFERS; src->num_capture_buffers = DEFAULT_PROP_NUM_CAPTURE_BUFFERS;
@ -411,6 +452,9 @@ gst_gentlsrc_set_property (GObject * object, guint property_id,
src = GST_GENTL_SRC (object); src = GST_GENTL_SRC (object);
switch (property_id) { switch (property_id) {
case PROP_PRODUCER:
src->producer_prop = g_value_get_enum (value);
break;
case PROP_INTERFACE_INDEX: case PROP_INTERFACE_INDEX:
src->interface_index = g_value_get_uint (value); src->interface_index = g_value_get_uint (value);
break; break;
@ -454,6 +498,9 @@ gst_gentlsrc_get_property (GObject * object, guint property_id,
src = GST_GENTL_SRC (object); src = GST_GENTL_SRC (object);
switch (property_id) { switch (property_id) {
case PROP_PRODUCER:
g_value_set_enum (value, src->producer_prop);
break;
case PROP_INTERFACE_INDEX: case PROP_INTERFACE_INDEX:
g_value_set_uint (value, src->interface_index); g_value_set_uint (value, src->interface_index);
break; break;
@ -730,7 +777,9 @@ gst_gentlsrc_get_payload_size (GstGenTlSrc * src)
guint32 val = 0; guint32 val = 0;
size_t datasize = 4; size_t datasize = 4;
// TODO: use node map // TODO: use node map
ret = GTL_GCReadPort (src->hDevPort, GENAPI_PAYLOAD_SIZE, &val, &datasize); ret =
GTL_GCReadPort (src->hDevPort, src->producer.payload_size, &val,
&datasize);
HANDLE_GTL_ERROR ("Failed to get payload size"); HANDLE_GTL_ERROR ("Failed to get payload size");
payload_size = GUINT32_FROM_BE (val); payload_size = GUINT32_FROM_BE (val);
GST_DEBUG_OBJECT (src, "Payload size defined by node map: %d", GST_DEBUG_OBJECT (src, "Payload size defined by node map: %d",
@ -788,14 +837,14 @@ gst_gentlsrc_get_gev_tick_frequency (GstGenTlSrc * src)
{ {
GC_ERROR ret; GC_ERROR ret;
if (!GENAPI_TICK_FREQ_HIGH || !GENAPI_TICK_FREQ_LOW) if (!src->producer.tick_frequency_high || !src->producer.tick_frequency_low)
return 0; return 0;
guint32 freq_low, freq_high; guint32 freq_low, freq_high;
size_t datasize = 4; size_t datasize = 4;
ret = GTL_GCReadPort (src->hDevPort, GENAPI_TICK_FREQ_LOW, &freq_low, &datasize); // GevTimestampTickFrequencyLow ret = GTL_GCReadPort (src->hDevPort, src->producer.tick_frequency_low, &freq_low, &datasize); // GevTimestampTickFrequencyLow
HANDLE_GTL_ERROR ("Failed to get GevTimestampTickFrequencyLow"); HANDLE_GTL_ERROR ("Failed to get GevTimestampTickFrequencyLow");
ret = GTL_GCReadPort (src->hDevPort, GENAPI_TICK_FREQ_HIGH, &freq_high, &datasize); // GevTimestampTickFrequencyHigh ret = GTL_GCReadPort (src->hDevPort, src->producer.tick_frequency_high, &freq_high, &datasize); // GevTimestampTickFrequencyHigh
HANDLE_GTL_ERROR ("Failed to get GevTimestampTickFrequencyHigh"); HANDLE_GTL_ERROR ("Failed to get GevTimestampTickFrequencyHigh");
guint64 tick_frequency = guint64 tick_frequency =
@ -818,12 +867,12 @@ gst_gentlsrc_get_gev_timestamp_ticks (GstGenTlSrc * src)
val = GUINT32_TO_BE (2); val = GUINT32_TO_BE (2);
datasize = sizeof (val); datasize = sizeof (val);
ret = GTL_GCWritePort (src->hDevPort, GENAPI_TIMESTAMP_CONTROL_LATCH, &val, &datasize); // GevTimestampControlLatch ret = GTL_GCWritePort (src->hDevPort, src->producer.timestamp_control_latch, &val, &datasize); // GevTimestampControlLatch
HANDLE_GTL_ERROR ("Failed to latch timestamp GevTimestampControlLatch"); HANDLE_GTL_ERROR ("Failed to latch timestamp GevTimestampControlLatch");
ret = GTL_GCReadPort (src->hDevPort, GENAPI_TIMESTAMP_VALUE_LOW, &ts_low, &datasize); // GevTimestampValueLow ret = GTL_GCReadPort (src->hDevPort, src->producer.timestamp_low, &ts_low, &datasize); // GevTimestampValueLow
HANDLE_GTL_ERROR ("Failed to get GevTimestampValueLow"); HANDLE_GTL_ERROR ("Failed to get GevTimestampValueLow");
ret = GTL_GCReadPort (src->hDevPort, GENAPI_TIMESTAMP_VALUE_HIGH, &ts_high, &datasize); // GevTimestampValueHigh ret = GTL_GCReadPort (src->hDevPort, src->producer.timestamp_high, &ts_high, &datasize); // GevTimestampValueHigh
HANDLE_GTL_ERROR ("Failed to get GevTimestampValueHigh"); HANDLE_GTL_ERROR ("Failed to get GevTimestampValueHigh");
guint64 ticks = GUINT64_FROM_BE ((guint64) ts_low << 32 | ts_high); guint64 ticks = GUINT64_FROM_BE ((guint64) ts_low << 32 | ts_high);
GST_LOG_OBJECT (src, "Timestamp ticks are %llu", ticks); GST_LOG_OBJECT (src, "Timestamp ticks are %llu", ticks);
@ -852,6 +901,14 @@ gst_gentlsrc_start (GstBaseSrc * bsrc)
GST_DEBUG_OBJECT (src, "start"); GST_DEBUG_OBJECT (src, "start");
if (src->producer_prop == GST_GENTLSRC_PRODUCER_BASLER) {
initialize_basler_addresses (&src->producer);
} else if (src->producer_prop == GST_GENTLSRC_PRODUCER_EVT) {
initialize_evt_addresses (&src->producer);
} else {
g_assert_not_reached ();
}
/* bind functions from CTI */ /* bind functions from CTI */
/* TODO: Enumerate CTI files in env var GENTL_GENTL64_PATH */ /* TODO: Enumerate CTI files in env var GENTL_GENTL64_PATH */
if (!gst_gentlsrc_bind_functions (src)) { if (!gst_gentlsrc_bind_functions (src)) {
@ -1120,15 +1177,17 @@ gst_gentlsrc_start (GstBaseSrc * bsrc)
// TODO: use GenTl node map for this // TODO: use GenTl node map for this
guint32 val = 0; guint32 val = 0;
size_t datasize = 4; size_t datasize = 4;
ret = GTL_GCReadPort (src->hDevPort, GENAPI_WIDTH, &val, &datasize); ret = GTL_GCReadPort (src->hDevPort, src->producer.width, &val, &datasize);
HANDLE_GTL_ERROR ("Failed to get width"); HANDLE_GTL_ERROR ("Failed to get width");
width = GUINT32_FROM_BE (val); width = GUINT32_FROM_BE (val);
ret = GTL_GCReadPort (src->hDevPort, GENAPI_HEIGHT, &val, &datasize); ret = GTL_GCReadPort (src->hDevPort, src->producer.height, &val, &datasize);
HANDLE_GTL_ERROR ("Failed to get height"); HANDLE_GTL_ERROR ("Failed to get height");
height = GUINT32_FROM_BE (val); height = GUINT32_FROM_BE (val);
GST_DEBUG_OBJECT (src, "Width and height %dx%d", width, height); GST_DEBUG_OBJECT (src, "Width and height %dx%d", width, height);
ret = GTL_GCReadPort (src->hDevPort, GENAPI_PIXFMT, &val, &datasize); ret =
GTL_GCReadPort (src->hDevPort, src->producer.pixel_format, &val,
&datasize);
HANDLE_GTL_ERROR ("Failed to get height"); HANDLE_GTL_ERROR ("Failed to get height");
const char *genicam_pixfmt; const char *genicam_pixfmt;
guint32 pixfmt_enum = GUINT32_FROM_BE (val); guint32 pixfmt_enum = GUINT32_FROM_BE (val);
@ -1204,15 +1263,19 @@ gst_gentlsrc_start (GstBaseSrc * bsrc)
/* set AcquisitionMode to Continuous */ /* set AcquisitionMode to Continuous */
// TODO: "Continuous" value can have different integer values, we need // TODO: "Continuous" value can have different integer values, we need
// to look it up in the node map (EVT is 0, Basler is 2) // to look it up in the node map (EVT is 0, Basler is 2)
val = GUINT32_TO_BE (0); val = GUINT32_TO_BE (src->producer.acquisition_mode_value);
datasize = sizeof (val); datasize = sizeof (val);
ret = GTL_GCWritePort (src->hDevPort, GENAPI_ACQMODE, &val, &datasize); ret =
GTL_GCWritePort (src->hDevPort, src->producer.acquisition_mode, &val,
&datasize);
HANDLE_GTL_ERROR ("Failed to start device acquisition"); HANDLE_GTL_ERROR ("Failed to start device acquisition");
/* send AcquisitionStart command */ /* send AcquisitionStart command */
val = GUINT32_TO_BE (1); val = GUINT32_TO_BE (1);
datasize = sizeof (val); datasize = sizeof (val);
ret = GTL_GCWritePort (src->hDevPort, GENAPI_ACQSTART, &val, &datasize); ret =
GTL_GCWritePort (src->hDevPort, src->producer.acquisition_start, &val,
&datasize);
HANDLE_GTL_ERROR ("Failed to start device acquisition"); HANDLE_GTL_ERROR ("Failed to start device acquisition");
} }
@ -1263,7 +1326,8 @@ gst_gentlsrc_stop (GstBaseSrc * bsrc)
guint32 val = GUINT32_TO_BE (1); guint32 val = GUINT32_TO_BE (1);
gsize datasize = sizeof (val); gsize datasize = sizeof (val);
GC_ERROR ret = GC_ERROR ret =
GTL_GCWritePort (src->hDevPort, GENAPI_ACQSTOP, &val, &datasize); GTL_GCWritePort (src->hDevPort, src->producer.acquisition_stop, &val,
&datasize);
GTL_DSStopAcquisition (src->hDS, ACQ_STOP_FLAGS_DEFAULT); GTL_DSStopAcquisition (src->hDS, ACQ_STOP_FLAGS_DEFAULT);
GTL_DSFlushQueue (src->hDS, ACQ_QUEUE_INPUT_TO_OUTPUT); GTL_DSFlushQueue (src->hDS, ACQ_QUEUE_INPUT_TO_OUTPUT);

View File

@ -38,6 +38,40 @@ G_BEGIN_DECLS
typedef struct _GstGenTlSrc GstGenTlSrc; typedef struct _GstGenTlSrc GstGenTlSrc;
typedef struct _GstGenTlSrcClass GstGenTlSrcClass; typedef struct _GstGenTlSrcClass GstGenTlSrcClass;
typedef struct _GstGenTlProducer GstGenTlProducer;
struct _GstGenTlProducer
{
gchar* cti_path;
guint32 acquisition_mode_value;
guint64 width;
guint64 height;
guint64 pixel_format;
guint64 payload_size;
guint64 acquisition_mode;
guint64 acquisition_start;
guint64 acquisition_stop;
guint64 tick_frequency_low;
guint64 tick_frequency_high;
guint64 timestamp_control_latch;
guint64 timestamp_low;
guint64 timestamp_high;
};
/**
* GstGenTlSrcProducer:
* @GST_GENTLSRC_PRODUCER_BASLER: Basler producer
* @GST_GENTLSRC_PRODUCER_EVT: EVT producer
*
* Producer to use.
*/
typedef enum {
GST_GENTLSRC_PRODUCER_BASLER,
GST_GENTLSRC_PRODUCER_EVT,
} GstGenTlSrcProducer;
struct _GstGenTlSrc struct _GstGenTlSrc
{ {
GstPushSrc base_gentlsrc; GstPushSrc base_gentlsrc;
@ -50,8 +84,10 @@ struct _GstGenTlSrc
PORT_HANDLE hDevPort; PORT_HANDLE hDevPort;
EVENT_HANDLE hNewBufferEvent; EVENT_HANDLE hNewBufferEvent;
char error_string[MAX_ERROR_STRING_LEN]; char error_string[MAX_ERROR_STRING_LEN];
GstGenTlProducer producer;
/* properties */ /* properties */
GstGenTlSrcProducer producer_prop;
guint interface_index; guint interface_index;
gchar *interface_id; gchar *interface_id;
guint device_index; guint device_index;