From 9e59d2f769c2c8d27d0d8667c0b5bdb55ccebf23 Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Thu, 7 Nov 2024 16:50:48 +0100 Subject: [PATCH] camera: USB maximum transfer size helper --- src/arvcamera.c | 33 +++++++++++++++++++++++++++++++++ src/arvcamera.h | 1 + src/arvcameratest.c | 11 ++++++++++- src/arvuvdevice.c | 24 +++++++++++++++++++++++- src/arvuvdevice.h | 3 ++- src/arvuvstream.c | 38 ++++++++++++++------------------------ src/arvuvstreamprivate.h | 8 ++++++-- 7 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/arvcamera.c b/src/arvcamera.c index a0de22faa..0e679b300 100644 --- a/src/arvcamera.c +++ b/src/arvcamera.c @@ -3880,6 +3880,39 @@ arv_camera_uv_set_usb_mode (ArvCamera *camera, ArvUvUsbMode usb_mode) #endif } +/** + * arv_camera_uv_set_maximum_transfer_size: + * @camera: a #ArvCamera + * @size: maximum bulk transfer size, in bytes + * + * Set the maximum size when asking for a USB bulk transfer. The default value should work most of the time, but you may + * have to tweak this setting in order to get reliable transfers. + * + * ::: note "Help needed" + * It would be nice to be able to compute a working value for any OS/driver combination aravis is + * running on. If someone knows how to do that, please open an issue (or event better, a merge request) on + * the aravis [issue tracker]. + * + * On linux, there seems to be this kernel parameter that could be used: + * `/sys/module/usbcore/parameters/usbfs_memory_mb`. + * + * Since: 0.10.0 + */ + +void +arv_camera_uv_set_maximum_transfer_size (ArvCamera *camera, guint64 size) +{ +#if ARAVIS_HAS_USB + ArvCameraPrivate *priv = arv_camera_get_instance_private (camera); +#endif + + g_return_if_fail (arv_camera_is_uv_device (camera)); + +#if ARAVIS_HAS_USB + arv_uv_device_set_maximum_transfer_size (ARV_UV_DEVICE (priv->device), size); +#endif +} + /** * arv_camera_is_gentl_device: * @camera: a #ArvCamera diff --git a/src/arvcamera.h b/src/arvcamera.h index 3a3f2083a..023139752 100644 --- a/src/arvcamera.h +++ b/src/arvcamera.h @@ -270,6 +270,7 @@ ARV_API void arv_camera_uv_set_bandwidth (ArvCamera *camera, guint bandwidth, ARV_API guint arv_camera_uv_get_bandwidth (ArvCamera *camera, GError **error); ARV_API void arv_camera_uv_get_bandwidth_bounds (ArvCamera *camera, guint *min, guint *max, GError **error); ARV_API void arv_camera_uv_set_usb_mode (ArvCamera *camera, ArvUvUsbMode usb_mode); +ARV_API void arv_camera_uv_set_maximum_transfer_size (ArvCamera *camera, guint64 size); ARV_API gboolean arv_camera_is_gentl_device (ArvCamera *camera); diff --git a/src/arvcameratest.c b/src/arvcameratest.c index cde8fa870..eda8363f5 100644 --- a/src/arvcameratest.c +++ b/src/arvcameratest.c @@ -40,6 +40,7 @@ static char *arv_option_range_check = NULL; static char *arv_option_access_check = NULL; static int arv_option_duration_s = -1; static char *arv_option_uv_usb_mode = NULL; +static guint arv_option_uv_usb_maximum_transfer_size = 0; static gboolean arv_option_show_version = FALSE; static gboolean arv_option_gv_allow_broadcast_discovery_ack = FALSE; static char *arv_option_gv_port_range = NULL; @@ -159,6 +160,12 @@ static const GOptionEntry arv_option_entries[] = &arv_option_uv_usb_mode, "USB device I/O mode", "{sync|async}" }, + { + "usb-maximum-transfer-size", '\0', 0, G_OPTION_ARG_INT, + &arv_option_uv_usb_maximum_transfer_size, + "USB maximum transfer size", + "}" + }, { "chunks", 'u', 0, G_OPTION_ARG_STRING, &arv_option_chunks, "Chunks", @@ -570,8 +577,10 @@ main (int argc, char **argv) if (arv_camera_is_uv_device (camera)) { if (error == NULL) arv_camera_uv_set_usb_mode (camera, usb_mode); + if (error == NULL && arv_option_uv_usb_maximum_transfer_size > 0) + arv_camera_uv_set_maximum_transfer_size (camera, arv_option_uv_usb_maximum_transfer_size); if (error == NULL && arv_option_bandwidth_limit >= 0) - arv_camera_uv_set_bandwidth (camera, arv_option_bandwidth_limit, &error); + arv_camera_uv_set_bandwidth (camera, arv_option_bandwidth_limit, &error); } if (arv_camera_is_gv_device (camera)) { diff --git a/src/arvuvdevice.c b/src/arvuvdevice.c index f0dcec531..7640d1525 100644 --- a/src/arvuvdevice.c +++ b/src/arvuvdevice.c @@ -77,6 +77,7 @@ typedef struct { gboolean disconnected; ArvUvUsbMode usb_mode; + guint64 maximum_transfer_size; int event_thread_run; GThread* event_thread; @@ -211,7 +212,8 @@ static ArvStream * arv_uv_device_create_stream (ArvDevice *device, ArvStreamCallback callback, void *user_data, GDestroyNotify destroy, GError **error) { ArvUvDevicePrivate *priv = arv_uv_device_get_instance_private (ARV_UV_DEVICE (device)); - return arv_uv_stream_new (ARV_UV_DEVICE (device), callback, user_data, destroy, priv->usb_mode, error); + return arv_uv_stream_new (ARV_UV_DEVICE (device), callback, user_data, destroy, + priv->usb_mode, priv->maximum_transfer_size, error); } static gboolean @@ -940,6 +942,25 @@ arv_uv_device_set_usb_mode (ArvUvDevice *uv_device, ArvUvUsbMode usb_mode) priv->usb_mode = usb_mode; } +/** + * arv_uv_device_set_maximum_transfer_size: + * @uv_device: a #ArvUvDevice + * @size: maximum transfer size, in bytes + * + * Set the maximum transfer size for a USB bulk transfer. + * + * Since: 0.10.0 + */ + +void +arv_uv_device_set_maximum_transfer_size (ArvUvDevice *uv_device, guint64 size) +{ + ArvUvDevicePrivate *priv = arv_uv_device_get_instance_private (uv_device); + + g_return_if_fail (ARV_IS_UV_DEVICE (uv_device)); + + priv->maximum_transfer_size = size; +} /** * arv_uv_device_new: * @vendor: USB3 vendor string @@ -1085,6 +1106,7 @@ arv_uv_device_constructed (GObject *object) &priv->hotplug_cb_handle); priv->usb_mode = ARV_UV_USB_MODE_DEFAULT; + priv->maximum_transfer_size = ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT; priv->event_thread_run = 1; priv->event_thread = g_thread_new ( "arv_libusb", event_thread_func, priv); diff --git a/src/arvuvdevice.h b/src/arvuvdevice.h index 15f51a4e7..f52710fae 100644 --- a/src/arvuvdevice.h +++ b/src/arvuvdevice.h @@ -40,7 +40,8 @@ ARV_API ArvDevice * arv_uv_device_new (const char *vendor, const char *produc const char *serial_number, GError **error); ARV_API ArvDevice * arv_uv_device_new_from_guid (const char *guid, GError **error); -ARV_API void arv_uv_device_set_usb_mode (ArvUvDevice *uv_device, ArvUvUsbMode usb_mode); +ARV_API void arv_uv_device_set_usb_mode (ArvUvDevice *uv_device, ArvUvUsbMode usb_mode); +ARV_API void arv_uv_device_set_maximum_transfer_size (ArvUvDevice *uv_device, guint64 size); G_END_DECLS diff --git a/src/arvuvstream.c b/src/arvuvstream.c index d99ad12d7..173163bb2 100644 --- a/src/arvuvstream.c +++ b/src/arvuvstream.c @@ -36,9 +36,6 @@ #include #include -#define ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT (1*1024*1024) -#define ARV_UV_STREAM_N_MAXIMUM_SUBMITS 8 - #define ARV_UV_STREAM_POP_INPUT_BUFFER_TIMEOUT_MS 10 #define ARV_UV_STREAM_TRANSFER_WAIT_TIMEOUT_MS 10 @@ -1096,6 +1093,9 @@ arv_uv_stream_create_buffers (ArvStream *stream, guint n_buffers, size_t size, * @uv_device: a #ArvUvDevice * @callback: (scope call): image processing callback * @callback_data: (closure): user data for @callback + * @destroy: callback data destroy function + * @usb_mode: USB mode selection + * @maximum_transfer_size: maximum transfer size, in bytes * @error: a #GError placeholder, %NULL to ignore * * Return Value: (transfer full): a new #ArvStream. @@ -1103,14 +1103,15 @@ arv_uv_stream_create_buffers (ArvStream *stream, guint n_buffers, size_t size, ArvStream * arv_uv_stream_new (ArvUvDevice *uv_device, ArvStreamCallback callback, void *callback_data, GDestroyNotify destroy, - ArvUvUsbMode usb_mode, GError **error) + ArvUvUsbMode usb_mode, guint64 maximum_transfer_size, GError **error) { return g_initable_new (ARV_TYPE_UV_STREAM, NULL, error, "device", uv_device, "callback", callback, "callback-data", callback_data, - "destroy-notify", destroy, + "destroy-notify", destroy, "usb-mode", usb_mode, + "maximum-transfer-size", maximum_transfer_size, NULL); } @@ -1255,25 +1256,14 @@ arv_uv_stream_class_init (ArvUvStreamClass *uv_stream_class) /** * ArvUvStream:maximum-transfer-size: * - * Maximum size when asking for a USB bulk transfer. The default value should work most of the time, but you may - * have to tweak this setting in order to get reliable transfers. This property can be changed at any time, but - * it will only have effect the next acquisition start. - * - * ::: note "Help needed" - * It would be nice to be able to compute a working value for any OS/driver combination aravis is - * running on. If someone knows how to do that, please open an issue (or event better, a merge request) on - * the aravis [issue tracker]. - * - * On linux, there seems to be this kernel parameter that could be used: - * `/sys/module/usbcore/parameters/usbfs_memory_mb`. - * + * Maximum size when asking for a USB bulk transfer. */ g_object_class_install_property ( - object_class, ARV_UV_STREAM_PROPERTY_MAXIMUM_TRANSFER_SIZE, - g_param_spec_uint64 ("maximum-transfer-size", "Maximum transfer size", - "USB maximum transfer size", - 1024, 1024 * 1024 * 1024, - ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT, - G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS) - ); + object_class, ARV_UV_STREAM_PROPERTY_MAXIMUM_TRANSFER_SIZE, + g_param_spec_uint64 ("maximum-transfer-size", "Maximum transfer size", + "USB maximum transfer size", + 1024, 1024 * 1024 * 1024, + ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS) + ); } diff --git a/src/arvuvstreamprivate.h b/src/arvuvstreamprivate.h index 337bc6a6b..505033316 100644 --- a/src/arvuvstreamprivate.h +++ b/src/arvuvstreamprivate.h @@ -33,8 +33,12 @@ G_BEGIN_DECLS -ArvStream * arv_uv_stream_new (ArvUvDevice *uv_device, ArvStreamCallback callback, void *user_data, GDestroyNotify destroy, - ArvUvUsbMode usb_mode, GError **error); +#define ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT (1*1024*1024) +#define ARV_UV_STREAM_N_MAXIMUM_SUBMITS 8 + +ArvStream * arv_uv_stream_new (ArvUvDevice *uv_device, + ArvStreamCallback callback, void *user_data, GDestroyNotify destroy, + ArvUvUsbMode usb_mode, guint64 maximum_transfer_size, GError **error); G_END_DECLS