@@ -19,44 +19,75 @@ extern "C" {
19
19
k4a_transformation_t transformation_handle;
20
20
k4a_calibration_t calibration_handle;
21
21
k4a_device_t device;
22
+ short thread_safe;
22
23
} device_container;
23
24
#define MAX_DEVICES 32
24
25
device_container devices[MAX_DEVICES];
25
26
27
+ static PyThreadState* _gil_release (uint32_t device_id) {
28
+ return NULL ;
29
+ PyThreadState *thread_state = NULL ;
30
+ if (devices[device_id].thread_safe == 0 ) {
31
+ thread_state = PyEval_SaveThread ();
32
+ }
33
+ return thread_state;
34
+ }
35
+
36
+ static void _gil_restore (PyThreadState *thread_state) {
37
+ if (thread_state != NULL ) {
38
+ PyEval_RestoreThread (thread_state);
39
+ }
40
+ }
41
+
26
42
static PyObject* device_open (PyObject* self, PyObject* args){
27
43
uint32_t device_id;
28
- PyArg_ParseTuple (args, " I" , &device_id);
29
- k4a_result_t result = k4a_device_open (device_id, &devices[device_id].device );
44
+ short thread_safe;
45
+ PyThreadState *thread_state;
46
+ PyArg_ParseTuple (args, " IH" , &device_id, &thread_safe);
30
47
48
+ devices[device_id].thread_safe = thread_safe;
49
+ thread_state = _gil_release (device_id);
50
+ k4a_result_t result = k4a_device_open (device_id, &devices[device_id].device );
51
+ _gil_restore (thread_state);
31
52
return Py_BuildValue (" I" , result);
32
53
}
33
54
34
55
static PyObject* device_close (PyObject* self, PyObject* args){
35
56
uint32_t device_id;
57
+ PyThreadState *thread_state;
36
58
PyArg_ParseTuple (args, " I" , &device_id);
59
+
60
+ thread_state = _gil_release (device_id);
37
61
k4a_device_close (devices[device_id].device );
62
+ _gil_restore (thread_state);
63
+
38
64
return Py_BuildValue (" I" , K4A_RESULT_SUCCEEDED);
39
65
}
40
66
41
67
static PyObject* device_get_sync_jack (PyObject* self, PyObject* args){
42
68
uint32_t device_id;
69
+ PyThreadState *thread_state;
43
70
bool in_jack = 0 ;
44
71
bool out_jack = 0 ;
45
72
PyArg_ParseTuple (args, " I" , &device_id);
46
-
73
+
74
+ thread_state = _gil_release (device_id);
47
75
k4a_result_t result = k4a_device_get_sync_jack (devices[device_id].device , &in_jack, &out_jack);
76
+ _gil_restore (thread_state);
48
77
49
78
return Py_BuildValue (" III" , result, in_jack, out_jack);
50
79
}
51
80
52
81
static PyObject* device_get_color_control (PyObject* self, PyObject* args){
53
82
uint32_t device_id;
83
+ PyThreadState *thread_state;
54
84
k4a_color_control_command_t command;
55
85
k4a_color_control_mode_t mode;
56
86
int32_t value = 0 ;
57
87
PyArg_ParseTuple (args, " II" , &device_id, &command);
58
-
88
+ thread_state = _gil_release (device_id);
59
89
k4a_result_t result = k4a_device_get_color_control (devices[device_id].device , command, &mode, &value);
90
+ _gil_restore (thread_state);
60
91
if (result == K4A_RESULT_FAILED) {
61
92
return Py_BuildValue (" III" , 0 , 0 , 0 );
62
93
}
@@ -65,12 +96,15 @@ extern "C" {
65
96
66
97
static PyObject* device_set_color_control (PyObject* self, PyObject* args){
67
98
uint32_t device_id;
99
+ PyThreadState *thread_state;
68
100
k4a_color_control_command_t command = K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE;
69
101
k4a_color_control_mode_t mode = K4A_COLOR_CONTROL_MODE_MANUAL;
70
102
int32_t value = 0 ;
71
103
PyArg_ParseTuple (args, " IIII" , &device_id, &command, &mode, &value);
72
104
105
+ thread_state = _gil_release (device_id);
73
106
k4a_result_t result = k4a_device_set_color_control (devices[device_id].device , command, mode, value);
107
+ _gil_restore (thread_state);
74
108
if (result == K4A_RESULT_FAILED) {
75
109
return Py_BuildValue (" I" , K4A_RESULT_FAILED);
76
110
}
@@ -79,6 +113,7 @@ extern "C" {
79
113
80
114
static PyObject* device_get_color_control_capabilities (PyObject* self, PyObject* args){
81
115
uint32_t device_id;
116
+ PyThreadState *thread_state;
82
117
k4a_color_control_command_t command;
83
118
bool supports_auto;
84
119
int32_t min_value;
@@ -88,8 +123,9 @@ extern "C" {
88
123
k4a_color_control_mode_t default_mode;
89
124
PyArg_ParseTuple (args, " II" , &device_id, &command);
90
125
91
-
126
+ thread_state = _gil_release (device_id);
92
127
k4a_result_t result = k4a_device_get_color_control_capabilities (devices[device_id].device , command, &supports_auto, &min_value, &max_value, &step_value, &default_value, &default_mode);
128
+ _gil_restore (thread_state);
93
129
if (result == K4A_RESULT_FAILED) {
94
130
return Py_BuildValue (" IIIIIII" , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
95
131
}
@@ -98,6 +134,7 @@ extern "C" {
98
134
99
135
static PyObject* device_start_cameras (PyObject* self, PyObject* args){
100
136
uint32_t device_id;
137
+ PyThreadState *thread_state;
101
138
k4a_device_configuration_t config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
102
139
PyArg_ParseTuple (args, " IIIIIIIIII" , &device_id,
103
140
&config.color_format ,
@@ -108,45 +145,57 @@ extern "C" {
108
145
&config.disable_streaming_indicator );
109
146
110
147
k4a_result_t result;
148
+ thread_state = _gil_release (device_id);
111
149
result = k4a_device_get_calibration (devices[device_id].device , config.depth_mode , config.color_resolution , &devices[device_id].calibration_handle );
112
150
if (result == K4A_RESULT_FAILED) {
151
+ _gil_restore (thread_state);
113
152
return Py_BuildValue (" I" , K4A_RESULT_FAILED);
114
153
}
115
154
devices[device_id].transformation_handle = k4a_transformation_create (&devices[device_id].calibration_handle );
116
155
if (devices[device_id].transformation_handle == NULL ) {
156
+ _gil_restore (thread_state);
117
157
return Py_BuildValue (" I" , K4A_RESULT_FAILED);
118
158
}
119
159
result = k4a_device_start_cameras (devices[device_id].device , &config);
160
+ _gil_restore (thread_state);
120
161
return Py_BuildValue (" I" , result);
121
162
}
122
163
123
164
static PyObject* device_stop_cameras (PyObject* self, PyObject* args){
124
165
uint32_t device_id;
166
+ PyThreadState *thread_state;
125
167
PyArg_ParseTuple (args, " I" , &device_id);
168
+ thread_state = _gil_release (device_id);
126
169
if (devices[device_id].transformation_handle ) {
127
170
k4a_transformation_destroy (devices[device_id].transformation_handle );
128
171
}
129
172
if (devices[device_id].capture ) {
130
173
k4a_capture_release (devices[device_id].capture );
131
174
}
132
175
k4a_device_stop_cameras (devices[device_id].device );
176
+ _gil_restore (thread_state);
133
177
return Py_BuildValue (" I" , K4A_RESULT_SUCCEEDED);
134
178
}
135
179
136
180
static PyObject* device_get_capture (PyObject* self, PyObject* args){
137
181
uint32_t device_id;
182
+ PyThreadState *thread_state;
138
183
int32_t timeout;
139
184
PyArg_ParseTuple (args, " II" , &device_id, &timeout);
185
+ thread_state = _gil_release (device_id);
140
186
if (devices[device_id].capture ) {
141
187
k4a_capture_release (devices[device_id].capture );
142
188
}
143
189
k4a_capture_create (&devices[device_id].capture );
144
- k4a_wait_result_t result = k4a_device_get_capture (devices[device_id].device , &devices[device_id].capture , timeout);
190
+ k4a_wait_result_t result;
191
+ result = k4a_device_get_capture (devices[device_id].device , &devices[device_id].capture , timeout);
192
+ _gil_restore (thread_state);
145
193
return Py_BuildValue (" I" , result);
146
194
}
147
195
148
196
static PyObject* calibration_set_from_raw (PyObject* self, PyObject* args){
149
197
uint32_t device_id;
198
+ PyThreadState *thread_state;
150
199
char * raw_calibration;
151
200
k4a_device_configuration_t config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
152
201
PyArg_ParseTuple (args, " IsIIIIIIIII" , &device_id,
@@ -159,37 +208,44 @@ extern "C" {
159
208
size_t raw_calibration_size = strlen (raw_calibration) + 1 ;
160
209
k4a_result_t result;
161
210
211
+ thread_state = _gil_release (device_id);
162
212
result = k4a_calibration_get_from_raw (raw_calibration,
163
213
raw_calibration_size, config.depth_mode ,
164
214
config.color_resolution , &devices[device_id].calibration_handle );
165
215
if (result == K4A_RESULT_FAILED) {
216
+ _gil_restore (thread_state);
166
217
return Py_BuildValue (" I" , K4A_RESULT_FAILED);
167
218
}
168
219
if (devices[device_id].transformation_handle ) {
169
220
k4a_transformation_destroy (devices[device_id].transformation_handle );
170
221
}
171
222
devices[device_id].transformation_handle = k4a_transformation_create (&devices[device_id].calibration_handle );
223
+ _gil_restore (thread_state);
172
224
return Py_BuildValue (" I" , K4A_RESULT_SUCCEEDED);
173
225
}
174
226
175
227
static PyObject* device_get_calibration (PyObject* self, PyObject* args){
176
228
uint32_t device_id;
229
+ PyThreadState *thread_state;
177
230
k4a_buffer_result_t result;
178
231
size_t data_size;
179
232
PyArg_ParseTuple (args, " I" , &device_id);
180
-
233
+ thread_state = _gil_release (device_id);
181
234
result = k4a_device_get_raw_calibration (devices[device_id].device , NULL , &data_size);
182
235
if (result == K4A_BUFFER_RESULT_FAILED) {
236
+ _gil_restore (thread_state);
183
237
return Py_BuildValue (" " );
184
238
}
185
239
uint8_t * data = (uint8_t *) malloc (data_size);
186
240
result = k4a_device_get_raw_calibration (devices[device_id].device , data, &data_size);
187
241
if (result == K4A_BUFFER_RESULT_FAILED) {
242
+ _gil_restore (thread_state);
188
243
return Py_BuildValue (" " );
189
244
}
190
245
191
246
PyObject* res = Py_BuildValue (" s" , data);
192
247
free (data);
248
+ _gil_restore (thread_state);
193
249
return res;
194
250
}
195
251
@@ -255,11 +311,13 @@ extern "C" {
255
311
static PyObject* transformation_depth_image_to_color_camera (
256
312
PyObject* self, PyObject* args){
257
313
uint32_t device_id;
314
+ PyThreadState *thread_state;
258
315
k4a_result_t res;
259
316
PyArrayObject *in_array;
260
317
k4a_color_resolution_t color_resolution;
261
318
PyArg_ParseTuple (args, " IO!I" , &device_id, &PyArray_Type, &in_array, &color_resolution);
262
319
320
+ thread_state = _gil_release (device_id);
263
321
k4a_image_t * depth_image_transformed = (k4a_image_t *) malloc (sizeof (k4a_image_t ));
264
322
265
323
k4a_image_t depth_image;
@@ -287,18 +345,22 @@ extern "C" {
287
345
}
288
346
289
347
if (K4A_RESULT_SUCCEEDED == res) {
348
+ _gil_restore (thread_state);
290
349
return PyArray_Return (np_depth_image);
291
350
}
292
351
else {
293
352
free (depth_image_transformed);
353
+ _gil_restore (thread_state);
294
354
return Py_BuildValue (" " );
295
355
}
296
356
}
297
357
298
358
static PyObject* device_get_color_image (PyObject* self, PyObject* args){
299
359
uint32_t device_id;
360
+ PyThreadState *thread_state;
300
361
PyArg_ParseTuple (args, " I" , &device_id);
301
362
k4a_result_t res;
363
+ thread_state = _gil_release (device_id);
302
364
k4a_image_t * color_image = (k4a_image_t *) malloc (sizeof (k4a_image_t ));
303
365
*color_image = k4a_capture_get_color_image (devices[device_id].capture );
304
366
PyArrayObject* np_color_image;
@@ -307,18 +369,23 @@ extern "C" {
307
369
}
308
370
309
371
if (K4A_RESULT_SUCCEEDED == res) {
372
+ _gil_restore (thread_state);
310
373
return PyArray_Return (np_color_image);
311
374
}
312
375
else {
313
376
free (color_image);
377
+ _gil_restore (thread_state);
314
378
return Py_BuildValue (" " );
315
379
}
316
380
}
317
381
318
382
static PyObject* device_get_depth_image (PyObject* self, PyObject* args){
319
383
k4a_result_t res;
320
384
uint32_t device_id;
385
+ PyThreadState *thread_state;
321
386
PyArg_ParseTuple (args, " I" , &device_id);
387
+
388
+ thread_state = _gil_release (device_id);
322
389
k4a_image_t * depth_image = (k4a_image_t *) malloc (sizeof (k4a_image_t ));
323
390
*depth_image = k4a_capture_get_depth_image (devices[device_id].capture );
324
391
@@ -328,18 +395,23 @@ extern "C" {
328
395
}
329
396
330
397
if (K4A_RESULT_SUCCEEDED == res) {
398
+ _gil_restore (thread_state);
331
399
return PyArray_Return (np_depth_image);
332
400
}
333
401
else {
334
402
free (depth_image);
403
+ _gil_restore (thread_state);
335
404
return Py_BuildValue (" " );
336
405
}
337
406
}
338
407
339
408
static PyObject* device_get_ir_image (PyObject* self, PyObject* args){
340
409
k4a_result_t res;
341
410
uint32_t device_id;
411
+ PyThreadState *thread_state;
342
412
PyArg_ParseTuple (args, " I" , &device_id);
413
+
414
+ thread_state = _gil_release (device_id);
343
415
k4a_image_t * ir_image = (k4a_image_t *) malloc (sizeof (k4a_image_t ));
344
416
*ir_image = k4a_capture_get_ir_image (devices[device_id].capture );
345
417
@@ -349,16 +421,19 @@ extern "C" {
349
421
}
350
422
351
423
if (K4A_RESULT_SUCCEEDED == res) {
424
+ _gil_restore (thread_state);
352
425
return PyArray_Return (np_ir_image);
353
426
}
354
427
else {
355
428
free (ir_image);
429
+ _gil_restore (thread_state);
356
430
return Py_BuildValue (" " );
357
431
}
358
432
}
359
433
360
434
static PyObject* calibration_3d_to_3d (PyObject* self, PyObject *args){
361
435
uint32_t device_id;
436
+ PyThreadState *thread_state;
362
437
k4a_result_t res;
363
438
k4a_float3_t source_point3d_mm;
364
439
k4a_float3_t target_point3d_mm;
@@ -375,7 +450,8 @@ extern "C" {
375
450
&source_point_z,
376
451
&source_camera,
377
452
&target_camera);
378
-
453
+
454
+ thread_state = _gil_release (device_id);
379
455
source_point3d_mm.xyz .x = source_point_x;
380
456
source_point3d_mm.xyz .y = source_point_y;
381
457
source_point3d_mm.xyz .z = source_point_z;
@@ -386,7 +462,7 @@ extern "C" {
386
462
source_camera,
387
463
target_camera,
388
464
&target_point3d_mm);
389
-
465
+ _gil_restore (thread_state);
390
466
if (res == K4A_RESULT_FAILED ) {
391
467
return Py_BuildValue (" I" , K4A_RESULT_FAILED);
392
468
}
@@ -396,6 +472,7 @@ extern "C" {
396
472
397
473
static PyObject* calibration_2d_to_3d (PyObject* self, PyObject *args){
398
474
uint32_t device_id;
475
+ PyThreadState *thread_state;
399
476
int source_point_x;
400
477
int source_point_y;
401
478
float source_depth_mm;
@@ -413,7 +490,8 @@ extern "C" {
413
490
&source_depth_mm,
414
491
&source_camera,
415
492
&target_camera);
416
-
493
+
494
+ thread_state = _gil_release (device_id);
417
495
source_point2d.xy .x = source_point_x;
418
496
source_point2d.xy .y = source_point_y;
419
497
@@ -425,7 +503,7 @@ extern "C" {
425
503
target_camera,
426
504
&target_point3d_mm,
427
505
&valid);
428
-
506
+ _gil_restore (thread_state);
429
507
if (res == K4A_RESULT_FAILED ) {
430
508
return Py_BuildValue (" I" , K4A_RESULT_FAILED);
431
509
}
0 commit comments