Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uvstream: make maximum transfer size configurable #958

Merged
merged 2 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/arvcamera.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]<https://github.com/AravisProject/aravis/issues>.
*
* 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
Expand Down
1 change: 1 addition & 0 deletions src/arvcamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
11 changes: 10 additions & 1 deletion src/arvcameratest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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",
"<n_bytes>}"
},
{
"chunks", 'u', 0, G_OPTION_ARG_STRING,
&arv_option_chunks, "Chunks",
Expand Down Expand Up @@ -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)) {
Expand Down
24 changes: 23 additions & 1 deletion src/arvuvdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ typedef struct {
gboolean disconnected;

ArvUvUsbMode usb_mode;
guint64 maximum_transfer_size;

int event_thread_run;
GThread* event_thread;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/arvuvdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
49 changes: 39 additions & 10 deletions src/arvuvstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,13 @@
#include <libusb.h>
#include <string.h>

#define ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE (1024*1024*1)
#define ARV_UV_STREAM_MAXIMUM_SUBMIT_TOTAL (8*1024*1024)

#define ARV_UV_STREAM_POP_INPUT_BUFFER_TIMEOUT_MS 10
#define ARV_UV_STREAM_TRANSFER_WAIT_TIMEOUT_MS 10

enum {
ARV_UV_STREAM_PROPERTY_0,
ARV_UV_STREAM_PROPERTY_USB_MODE
ARV_UV_STREAM_PROPERTY_USB_MODE,
ARV_UV_STREAM_PROPERTY_MAXIMUM_TRANSFER_SIZE,
} ArvUvStreamProperties;

/* Acquisition thread */
Expand Down Expand Up @@ -82,6 +80,7 @@ typedef struct {
guint32 payload_count;
size_t transfer1_size;
size_t trailer_size;
guint64 maximum_transfer_size;

gboolean cancel;

Expand All @@ -99,6 +98,7 @@ typedef struct {
GThread *thread;
ArvUvStreamThreadData *thread_data;
ArvUvUsbMode usb_mode;
guint64 maximum_transfer_size;

guint64 sirm_address;
} ArvUvStreamPrivate;
Expand All @@ -124,6 +124,8 @@ typedef struct {
size_t total_payload_transferred;
size_t expected_size;

guint64 maximum_submit_total;

guint8 *leader_buffer, *trailer_buffer;

int num_payload_transfers;
Expand Down Expand Up @@ -381,13 +383,16 @@ arv_uv_stream_buffer_context_new (ArvBuffer *buffer, ArvUvStreamThreadData *thre
int i;
size_t offset = 0;

ctx = g_new0 (ArvUvStreamBufferContext, 1);

ctx->buffer = NULL;
ctx->stream = thread_data->stream;
ctx->callback = thread_data->callback;
ctx->callback_data = thread_data->callback_data;
ctx->transfer_completed_mtx = &thread_data->stream_mtx;
ctx->transfer_completed_event = &thread_data->stream_event;
ctx->n_buffer_in_use = &thread_data->n_buffer_in_use;
ctx->maximum_submit_total = thread_data->maximum_transfer_size * ARV_UV_STREAM_N_MAXIMUM_SUBMITS;

ctx->leader_buffer = g_malloc (thread_data->leader_size);
ctx->leader_transfer = libusb_alloc_transfer (0);
Expand Down Expand Up @@ -465,7 +470,7 @@ static void
_submit_transfer (ArvUvStreamBufferContext* ctx, struct libusb_transfer* transfer, gboolean* cancel)
{
while (!g_atomic_int_get (cancel) &&
((g_atomic_int_get(ctx->total_submitted_bytes) + transfer->length) > ARV_UV_STREAM_MAXIMUM_SUBMIT_TOTAL)) {
((g_atomic_int_get(ctx->total_submitted_bytes) + transfer->length) > ctx->maximum_submit_total)) {
arv_uv_stream_buffer_context_wait_transfer_completed (ctx, ARV_UV_STREAM_TRANSFER_WAIT_TIMEOUT_MS);
}

Expand Down Expand Up @@ -666,7 +671,7 @@ arv_uv_stream_thread_sync (void *data)

arv_info_stream_thread ("Start sync USB3Vision stream thread");

incoming_buffer = g_malloc (ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE);
incoming_buffer = g_malloc (thread_data->maximum_transfer_size);

if (thread_data->callback != NULL)
thread_data->callback (thread_data->callback_data, ARV_STREAM_CALLBACK_TYPE_INIT, NULL);
Expand All @@ -684,7 +689,7 @@ arv_uv_stream_thread_sync (void *data)
transferred = 0;

if (buffer == NULL)
size = ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE;
size = thread_data->maximum_transfer_size;
else {
if (offset < buffer->priv->allocated_size)
size = MIN (thread_data->payload_size, buffer->priv->allocated_size - offset);
Expand Down Expand Up @@ -919,7 +924,10 @@ arv_uv_stream_start_acquisition (ArvStream *stream, GError **error)

arv_info_stream ("Required alignment = %d", alignment);

aligned_maximum_transfer_size = ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE / alignment * alignment;
/* keep a non mutated copy of maximum_transfer_size during the thread lifetime */
thread_data->maximum_transfer_size = priv->maximum_transfer_size;

aligned_maximum_transfer_size = thread_data->maximum_transfer_size / alignment * alignment;

if (si_req_leader_size < 1) {
arv_warning_stream ("Wrong SI_REQ_LEADER_SIZE value, using %d instead", aligned_maximum_transfer_size);
Expand Down Expand Up @@ -1085,21 +1093,25 @@ 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.
*/

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);
}

Expand Down Expand Up @@ -1160,6 +1172,9 @@ arv_uv_stream_set_property (GObject * object, guint prop_id,
case ARV_UV_STREAM_PROPERTY_USB_MODE:
priv->usb_mode = g_value_get_enum(value);
break;
case ARV_UV_STREAM_PROPERTY_MAXIMUM_TRANSFER_SIZE:
priv->maximum_transfer_size = g_value_get_uint64(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
Expand Down Expand Up @@ -1237,4 +1252,18 @@ arv_uv_stream_class_init (ArvUvStreamClass *uv_stream_class)
ARV_UV_USB_MODE_DEFAULT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
);

/**
* ArvUvStream:maximum-transfer-size:
*
* 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_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
);
}
8 changes: 6 additions & 2 deletions src/arvuvstreamprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading