v4l2-ruby 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +59 -0
- data/Rakefile +8 -0
- data/ext/v4l2/camera.c +1428 -0
- data/ext/v4l2/camera.h +131 -0
- data/ext/v4l2/extconf.rb +5 -0
- data/ext/v4l2/v4l2.c +967 -0
- data/lib/v4l2/version.rb +3 -0
- data/lib/v4l2.rb +5 -0
- data/v4l2-ruby.gemspec +38 -0
- metadata +98 -0
data/ext/v4l2/v4l2.c
ADDED
@@ -0,0 +1,967 @@
|
|
1
|
+
/*
|
2
|
+
* Video 4 Linux V2 for Ruby interface library.
|
3
|
+
*
|
4
|
+
* Copyright (C) 2015 Hiroshi Kuwagata. All rights reserved.
|
5
|
+
*/
|
6
|
+
|
7
|
+
/*
|
8
|
+
* $Id: v4l2.c 121 2016-11-18 04:32:27Z pi $
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include "ruby.h"
|
12
|
+
#include "ruby/encoding.h"
|
13
|
+
|
14
|
+
#include "camera.h"
|
15
|
+
|
16
|
+
#define N(x) (sizeof((x))/sizeof(*(x)))
|
17
|
+
|
18
|
+
extern rb_encoding* rb_utf8_encoding(void);
|
19
|
+
|
20
|
+
static VALUE module;
|
21
|
+
static VALUE camera_klass;
|
22
|
+
static VALUE control_klass;
|
23
|
+
static VALUE integer_klass;
|
24
|
+
static VALUE boolean_klass;
|
25
|
+
static VALUE menu_klass;
|
26
|
+
//static VALUE imenu_klass;
|
27
|
+
static VALUE menu_item_klass;
|
28
|
+
static VALUE frame_cap_klass;
|
29
|
+
static VALUE fmt_desc_klass;
|
30
|
+
|
31
|
+
static ID id_yuyv;
|
32
|
+
static ID id_yuv422;
|
33
|
+
static ID id_nv21;
|
34
|
+
static ID id_nv12;
|
35
|
+
static ID id_nv16;
|
36
|
+
static ID id_rgb565;
|
37
|
+
static ID id_mjpeg;
|
38
|
+
static ID id_h264;
|
39
|
+
static ID id_iv_name;
|
40
|
+
static ID id_iv_driver;
|
41
|
+
static ID id_iv_bus;
|
42
|
+
static ID id_iv_id;
|
43
|
+
static ID id_iv_max;
|
44
|
+
static ID id_iv_min;
|
45
|
+
static ID id_iv_step;
|
46
|
+
static ID id_iv_default;
|
47
|
+
static ID id_iv_items;
|
48
|
+
static ID id_iv_index;
|
49
|
+
static ID id_iv_width;
|
50
|
+
static ID id_iv_height;
|
51
|
+
static ID id_iv_rate;
|
52
|
+
static ID id_iv_fcc;
|
53
|
+
static ID id_iv_desc;
|
54
|
+
|
55
|
+
static void
|
56
|
+
rb_camera_free(void* ptr)
|
57
|
+
{
|
58
|
+
if (((camera_t*)ptr)->state != 6) {
|
59
|
+
camera_finalize( ptr);
|
60
|
+
}
|
61
|
+
|
62
|
+
free( ptr);
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE
|
66
|
+
rb_camera_alloc(VALUE self)
|
67
|
+
{
|
68
|
+
camera_t* ptr;
|
69
|
+
|
70
|
+
return Data_Make_Struct(camera_klass, camera_t, 0, rb_camera_free, ptr);
|
71
|
+
}
|
72
|
+
|
73
|
+
static VALUE
|
74
|
+
rb_camera_open(VALUE self, VALUE device)
|
75
|
+
{
|
76
|
+
VALUE ret;
|
77
|
+
|
78
|
+
ret = rb_obj_alloc(camera_klass);
|
79
|
+
rb_obj_call_init(ret, 1, &device);
|
80
|
+
|
81
|
+
return ret;
|
82
|
+
}
|
83
|
+
|
84
|
+
static VALUE
|
85
|
+
rb_camera_initialize(VALUE self, VALUE dev)
|
86
|
+
{
|
87
|
+
int err;
|
88
|
+
camera_t* ptr;
|
89
|
+
|
90
|
+
/*
|
91
|
+
* argument check
|
92
|
+
*/
|
93
|
+
Check_Type(dev, T_STRING);
|
94
|
+
|
95
|
+
/*
|
96
|
+
* strip object
|
97
|
+
*/
|
98
|
+
Data_Get_Struct(self, camera_t, ptr);
|
99
|
+
|
100
|
+
/*
|
101
|
+
* initialize struct
|
102
|
+
*/
|
103
|
+
err = camera_initialize(ptr, RSTRING_PTR(dev));
|
104
|
+
if (err) {
|
105
|
+
rb_raise(rb_eRuntimeError, "initialize camera context failed.");
|
106
|
+
}
|
107
|
+
|
108
|
+
/*
|
109
|
+
* set default instance variable
|
110
|
+
*/
|
111
|
+
rb_ivar_set(self, id_iv_name,
|
112
|
+
rb_enc_str_new_cstr(ptr->name, rb_utf8_encoding()));
|
113
|
+
rb_ivar_set(self, id_iv_driver,
|
114
|
+
rb_enc_str_new_cstr(ptr->driver, rb_utf8_encoding()));
|
115
|
+
rb_ivar_set(self, id_iv_bus,
|
116
|
+
rb_enc_str_new_cstr(ptr->bus, rb_utf8_encoding()));
|
117
|
+
|
118
|
+
return Qtrue;
|
119
|
+
}
|
120
|
+
|
121
|
+
static VALUE
|
122
|
+
rb_camera_close( VALUE self)
|
123
|
+
{
|
124
|
+
int err;
|
125
|
+
camera_t* ptr;
|
126
|
+
|
127
|
+
/*
|
128
|
+
* strip object
|
129
|
+
*/
|
130
|
+
Data_Get_Struct(self, camera_t, ptr);
|
131
|
+
|
132
|
+
/*
|
133
|
+
* convert
|
134
|
+
*/
|
135
|
+
err = camera_finalize(ptr);
|
136
|
+
if (err) {
|
137
|
+
rb_raise(rb_eRuntimeError, "finalize camera context failed.");
|
138
|
+
}
|
139
|
+
|
140
|
+
return Qnil;
|
141
|
+
}
|
142
|
+
|
143
|
+
static VALUE
|
144
|
+
get_menu_list(camera_t* ptr, int ctrl, int min, int max)
|
145
|
+
{
|
146
|
+
VALUE ret;
|
147
|
+
int i;
|
148
|
+
int err;
|
149
|
+
struct v4l2_querymenu item;
|
150
|
+
|
151
|
+
ret = rb_ary_new();
|
152
|
+
for (i = min; i <= max; i++) {
|
153
|
+
err = camera_get_menu_item(ptr, ctrl, i, &item);
|
154
|
+
if (!err) {
|
155
|
+
VALUE tmp;
|
156
|
+
|
157
|
+
tmp = rb_obj_alloc(menu_item_klass);
|
158
|
+
rb_ivar_set(tmp, id_iv_name, rb_str_new2((const char*)item.name));
|
159
|
+
rb_ivar_set(tmp, id_iv_index, INT2FIX(item.index));
|
160
|
+
|
161
|
+
rb_ary_push(ret, tmp);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
return ret;
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE
|
169
|
+
get_int_menu_list(camera_t* ptr, int ctrl, int min, int max)
|
170
|
+
{
|
171
|
+
VALUE ret;
|
172
|
+
int i;
|
173
|
+
int err;
|
174
|
+
struct v4l2_querymenu item;
|
175
|
+
|
176
|
+
ret = rb_ary_new();
|
177
|
+
for (i = min; i <= max; i++) {
|
178
|
+
err = camera_get_menu_item(ptr, ctrl, i, &item);
|
179
|
+
if (!err) {
|
180
|
+
VALUE tmp;
|
181
|
+
|
182
|
+
tmp = rb_obj_alloc(menu_item_klass);
|
183
|
+
rb_ivar_set(tmp, id_iv_name, rb_sprintf("%lld", item.value));
|
184
|
+
rb_ivar_set(tmp, id_iv_index, INT2FIX(item.index));
|
185
|
+
|
186
|
+
rb_ary_push(ret, tmp);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
return ret;
|
191
|
+
}
|
192
|
+
|
193
|
+
static VALUE
|
194
|
+
get_control_info(camera_t* ptr, int ctrl)
|
195
|
+
{
|
196
|
+
VALUE ret;
|
197
|
+
int err;
|
198
|
+
struct v4l2_queryctrl info;
|
199
|
+
|
200
|
+
ret = Qnil;
|
201
|
+
err = camera_get_control_info(ptr, ctrl, &info);
|
202
|
+
if (!err) {
|
203
|
+
switch (info.type) {
|
204
|
+
case V4L2_CTRL_TYPE_INTEGER:
|
205
|
+
ret = rb_obj_alloc(integer_klass);
|
206
|
+
rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
|
207
|
+
rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
|
208
|
+
rb_ivar_set(ret, id_iv_min, INT2FIX(info.minimum));
|
209
|
+
rb_ivar_set(ret, id_iv_max, INT2FIX(info.maximum));
|
210
|
+
rb_ivar_set(ret, id_iv_step, INT2FIX(info.step));
|
211
|
+
rb_ivar_set(ret, id_iv_default, INT2FIX(info.default_value));
|
212
|
+
break;
|
213
|
+
|
214
|
+
case V4L2_CTRL_TYPE_BOOLEAN:
|
215
|
+
ret = rb_obj_alloc(boolean_klass);
|
216
|
+
rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
|
217
|
+
rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
|
218
|
+
rb_ivar_set(ret, id_iv_default, (info.default_value)? Qtrue: Qfalse);
|
219
|
+
break;
|
220
|
+
|
221
|
+
case V4L2_CTRL_TYPE_MENU:
|
222
|
+
ret = rb_obj_alloc(menu_klass);
|
223
|
+
rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
|
224
|
+
rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
|
225
|
+
rb_ivar_set(ret, id_iv_default, INT2FIX(info.default_value));
|
226
|
+
rb_ivar_set(ret, id_iv_items,
|
227
|
+
get_menu_list(ptr, ctrl, info.minimum, info.maximum));
|
228
|
+
break;
|
229
|
+
|
230
|
+
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
231
|
+
ret = rb_obj_alloc(menu_klass);
|
232
|
+
rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
|
233
|
+
rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
|
234
|
+
rb_ivar_set(ret, id_iv_default, INT2FIX(info.default_value));
|
235
|
+
rb_ivar_set(ret, id_iv_items,
|
236
|
+
get_int_menu_list(ptr, ctrl, info.minimum, info.maximum));
|
237
|
+
break;
|
238
|
+
|
239
|
+
default:
|
240
|
+
fprintf(stderr, "unsupported type %d, name: %s\n",
|
241
|
+
info.type, info.name);
|
242
|
+
break;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
return ret;
|
247
|
+
}
|
248
|
+
|
249
|
+
static VALUE
|
250
|
+
rb_camera_get_controls(VALUE self)
|
251
|
+
{
|
252
|
+
VALUE ret;
|
253
|
+
camera_t* ptr;
|
254
|
+
int i;
|
255
|
+
VALUE info;
|
256
|
+
|
257
|
+
Data_Get_Struct(self, camera_t, ptr);
|
258
|
+
|
259
|
+
ret = rb_ary_new();
|
260
|
+
|
261
|
+
for (i = 0; i < 43; i++) {
|
262
|
+
info = get_control_info(ptr, V4L2_CID_BASE + i);
|
263
|
+
if (info != Qnil) rb_ary_push(ret, info);
|
264
|
+
}
|
265
|
+
|
266
|
+
for (i = 0; i < 30; i++) {
|
267
|
+
info = get_control_info(ptr, V4L2_CID_CAMERA_CLASS_BASE + i);
|
268
|
+
if (info != Qnil) rb_ary_push(ret, info);
|
269
|
+
}
|
270
|
+
|
271
|
+
for (i = 0; i < 20; i++) {
|
272
|
+
info = get_control_info(ptr, V4L2_CID_JPEG_CLASS_BASE + i);
|
273
|
+
if (info != Qnil) rb_ary_push(ret, info);
|
274
|
+
}
|
275
|
+
|
276
|
+
return ret;
|
277
|
+
}
|
278
|
+
|
279
|
+
static VALUE
|
280
|
+
get_framerate_list(camera_t* cam, struct v4l2_frmsize_discrete* size)
|
281
|
+
{
|
282
|
+
VALUE ret;
|
283
|
+
int i;
|
284
|
+
|
285
|
+
int err;
|
286
|
+
struct v4l2_frmivalenum intval;
|
287
|
+
VALUE rate;
|
288
|
+
|
289
|
+
ret = rb_ary_new();
|
290
|
+
|
291
|
+
for (i = 0; ; i++) {
|
292
|
+
err = camera_get_frame_rate(cam, V4L2_PIX_FMT_MJPEG,
|
293
|
+
size->width, size->height, i, &intval);
|
294
|
+
if (err) break;
|
295
|
+
|
296
|
+
if (intval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
|
297
|
+
rate = rb_rational_new(INT2FIX(intval.discrete.denominator),
|
298
|
+
INT2FIX(intval.discrete.numerator));
|
299
|
+
|
300
|
+
rb_ary_push(ret, rate);
|
301
|
+
}
|
302
|
+
}
|
303
|
+
|
304
|
+
return ret;
|
305
|
+
}
|
306
|
+
|
307
|
+
static uint32_t
|
308
|
+
to_pixfmt(VALUE fmt)
|
309
|
+
{
|
310
|
+
uint32_t ret;
|
311
|
+
ID sym;
|
312
|
+
|
313
|
+
sym = rb_to_id(fmt);
|
314
|
+
|
315
|
+
if (sym == id_yuyv || sym == id_yuv422) {
|
316
|
+
ret = V4L2_PIX_FMT_YUYV;
|
317
|
+
|
318
|
+
} else if (sym == id_nv12) {
|
319
|
+
ret = V4L2_PIX_FMT_NV12;
|
320
|
+
|
321
|
+
} else if (sym == id_nv21) {
|
322
|
+
ret = V4L2_PIX_FMT_NV21;
|
323
|
+
|
324
|
+
} else if (sym == id_nv16) {
|
325
|
+
ret = V4L2_PIX_FMT_NV16;
|
326
|
+
|
327
|
+
} else if (sym == id_rgb565) {
|
328
|
+
ret = V4L2_PIX_FMT_RGB565;
|
329
|
+
|
330
|
+
} else if (sym == id_mjpeg) {
|
331
|
+
ret = V4L2_PIX_FMT_MJPEG;
|
332
|
+
|
333
|
+
} else if (sym == id_h264) {
|
334
|
+
ret = V4L2_PIX_FMT_H264;
|
335
|
+
|
336
|
+
} else {
|
337
|
+
rb_raise(rb_eRuntimeError, "Unsupported pixel format.");
|
338
|
+
}
|
339
|
+
|
340
|
+
return ret;
|
341
|
+
}
|
342
|
+
|
343
|
+
static VALUE
|
344
|
+
rb_camera_get_support_formats(VALUE self)
|
345
|
+
{
|
346
|
+
VALUE ret;
|
347
|
+
camera_t* ptr;
|
348
|
+
|
349
|
+
int i;
|
350
|
+
int err;
|
351
|
+
struct v4l2_fmtdesc desc;
|
352
|
+
|
353
|
+
VALUE fmt;
|
354
|
+
VALUE fcc;
|
355
|
+
|
356
|
+
Data_Get_Struct(self, camera_t, ptr);
|
357
|
+
|
358
|
+
ret = rb_ary_new();
|
359
|
+
|
360
|
+
for (i = 0; ;i++) {
|
361
|
+
err = camera_get_format_desc(ptr, i, &desc);
|
362
|
+
if (err) break;
|
363
|
+
|
364
|
+
fmt = rb_obj_alloc(fmt_desc_klass);
|
365
|
+
fcc = rb_sprintf("%c%c%c%c",
|
366
|
+
desc.pixelformat >> 0 & 0xff,
|
367
|
+
desc.pixelformat >> 8 & 0xff,
|
368
|
+
desc.pixelformat >> 16 & 0xff,
|
369
|
+
desc.pixelformat >> 24 & 0xff);
|
370
|
+
rb_ivar_set(fmt, id_iv_fcc, fcc);
|
371
|
+
rb_ivar_set(fmt, id_iv_desc, rb_str_new2(desc.description));
|
372
|
+
|
373
|
+
rb_ary_push(ret, fmt);
|
374
|
+
}
|
375
|
+
|
376
|
+
return ret;
|
377
|
+
}
|
378
|
+
|
379
|
+
static void
|
380
|
+
make_dummy_capabilities(camera_t* ptr, VALUE ary, int max_width, int max_height)
|
381
|
+
{
|
382
|
+
struct v4l2_frmsize_discrete dsize;
|
383
|
+
VALUE capa;
|
384
|
+
|
385
|
+
if (max_width > max_height) {
|
386
|
+
/*
|
387
|
+
* when landscape
|
388
|
+
*/
|
389
|
+
|
390
|
+
for (dsize.width = 160; dsize.width < max_width; dsize.width *= 2) {
|
391
|
+
dsize.height = (dsize.width * 9) / 16;
|
392
|
+
|
393
|
+
capa = rb_obj_alloc(frame_cap_klass);
|
394
|
+
rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
|
395
|
+
rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
|
396
|
+
rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
|
397
|
+
|
398
|
+
rb_ary_push(ary, capa);
|
399
|
+
|
400
|
+
dsize.height = (dsize.width * 3) / 4;
|
401
|
+
|
402
|
+
capa = rb_obj_alloc(frame_cap_klass);
|
403
|
+
rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
|
404
|
+
rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
|
405
|
+
rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
|
406
|
+
|
407
|
+
rb_ary_push(ary, capa);
|
408
|
+
}
|
409
|
+
|
410
|
+
} else {
|
411
|
+
/*
|
412
|
+
* when portrate
|
413
|
+
*/
|
414
|
+
|
415
|
+
dsize.height = 160;
|
416
|
+
|
417
|
+
for (dsize.height = 160; dsize.height < max_height; dsize.height *= 2) {
|
418
|
+
dsize.width = (dsize.height * 9) / 16;
|
419
|
+
|
420
|
+
capa = rb_obj_alloc(frame_cap_klass);
|
421
|
+
rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
|
422
|
+
rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
|
423
|
+
rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
|
424
|
+
|
425
|
+
rb_ary_push(ary, capa);
|
426
|
+
|
427
|
+
dsize.width = (dsize.height * 3) / 4;
|
428
|
+
|
429
|
+
capa = rb_obj_alloc(frame_cap_klass);
|
430
|
+
rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
|
431
|
+
rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
|
432
|
+
rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
|
433
|
+
|
434
|
+
rb_ary_push(ary, capa);
|
435
|
+
}
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
static VALUE
|
440
|
+
rb_camera_get_frame_capabilities(VALUE self, VALUE fmt)
|
441
|
+
{
|
442
|
+
VALUE ret;
|
443
|
+
camera_t* ptr;
|
444
|
+
int i;
|
445
|
+
int j;
|
446
|
+
|
447
|
+
int err;
|
448
|
+
struct v4l2_frmsizeenum size;
|
449
|
+
|
450
|
+
VALUE capa;
|
451
|
+
VALUE list;
|
452
|
+
VALUE rate;
|
453
|
+
|
454
|
+
Check_Type(fmt, T_SYMBOL);
|
455
|
+
|
456
|
+
Data_Get_Struct(self, camera_t, ptr);
|
457
|
+
|
458
|
+
ret = rb_ary_new();
|
459
|
+
|
460
|
+
for (i = 0; ;i++){
|
461
|
+
err = camera_get_frame_size(ptr, to_pixfmt(fmt), i, &size);
|
462
|
+
if (err) break;
|
463
|
+
|
464
|
+
if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
|
465
|
+
capa = rb_obj_alloc(frame_cap_klass);
|
466
|
+
rb_ivar_set(capa, id_iv_width, INT2NUM(size.discrete.width));
|
467
|
+
rb_ivar_set(capa, id_iv_height, INT2NUM(size.discrete.height));
|
468
|
+
rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &size.discrete));
|
469
|
+
|
470
|
+
rb_ary_push(ret, capa);
|
471
|
+
|
472
|
+
} else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
|
473
|
+
make_dummy_capabilities(ptr, ret,
|
474
|
+
size.stepwise.max_width,
|
475
|
+
size.stepwise.max_height);
|
476
|
+
break;
|
477
|
+
}
|
478
|
+
}
|
479
|
+
|
480
|
+
return ret;
|
481
|
+
}
|
482
|
+
|
483
|
+
static VALUE
|
484
|
+
rb_camera_set_control(VALUE self, VALUE id, VALUE val)
|
485
|
+
{
|
486
|
+
camera_t* ptr;
|
487
|
+
int err;
|
488
|
+
|
489
|
+
Data_Get_Struct(self, camera_t, ptr);
|
490
|
+
|
491
|
+
err = camera_set_control(ptr, FIX2INT(id), FIX2INT(val));
|
492
|
+
if (err) {
|
493
|
+
rb_raise(rb_eRuntimeError, "set control failed.");
|
494
|
+
}
|
495
|
+
|
496
|
+
return Qnil;
|
497
|
+
}
|
498
|
+
|
499
|
+
static VALUE
|
500
|
+
rb_camera_get_control(VALUE self, VALUE id)
|
501
|
+
{
|
502
|
+
camera_t* ptr;
|
503
|
+
int err;
|
504
|
+
int32_t value;
|
505
|
+
|
506
|
+
Data_Get_Struct( self, camera_t, ptr);
|
507
|
+
|
508
|
+
err = camera_get_control(ptr, FIX2INT(id), &value);
|
509
|
+
if (err) {
|
510
|
+
rb_raise(rb_eRuntimeError, "get control failed.");
|
511
|
+
}
|
512
|
+
|
513
|
+
return INT2FIX(value);
|
514
|
+
}
|
515
|
+
|
516
|
+
static VALUE
|
517
|
+
rb_camera_set_format(VALUE self, VALUE fmt)
|
518
|
+
{
|
519
|
+
camera_t* ptr;
|
520
|
+
int err;
|
521
|
+
|
522
|
+
/*
|
523
|
+
* argument check
|
524
|
+
*/
|
525
|
+
Check_Type(fmt, T_SYMBOL);
|
526
|
+
|
527
|
+
/*
|
528
|
+
* strip object
|
529
|
+
*/
|
530
|
+
Data_Get_Struct(self, camera_t, ptr);
|
531
|
+
|
532
|
+
/*
|
533
|
+
* set parameter
|
534
|
+
*/
|
535
|
+
err = camera_set_format(ptr, to_pixfmt(fmt));
|
536
|
+
if (err) {
|
537
|
+
rb_raise(rb_eRuntimeError, "set format failed.");
|
538
|
+
}
|
539
|
+
|
540
|
+
return Qnil;
|
541
|
+
}
|
542
|
+
|
543
|
+
static VALUE
|
544
|
+
rb_camera_get_image_width(VALUE self)
|
545
|
+
{
|
546
|
+
int ret;
|
547
|
+
camera_t* ptr;
|
548
|
+
int err;
|
549
|
+
|
550
|
+
/*
|
551
|
+
* strip object
|
552
|
+
*/
|
553
|
+
Data_Get_Struct(self, camera_t, ptr);
|
554
|
+
|
555
|
+
/*
|
556
|
+
* get parameter
|
557
|
+
*/
|
558
|
+
err = camera_get_image_width(ptr, &ret);
|
559
|
+
if (err) {
|
560
|
+
rb_raise(rb_eRuntimeError, "get image width failed.");
|
561
|
+
}
|
562
|
+
|
563
|
+
return INT2FIX(ret);
|
564
|
+
}
|
565
|
+
|
566
|
+
static VALUE
|
567
|
+
rb_camera_set_image_width(VALUE self, VALUE val)
|
568
|
+
{
|
569
|
+
camera_t* ptr;
|
570
|
+
int err;
|
571
|
+
|
572
|
+
/*
|
573
|
+
* argument check
|
574
|
+
*/
|
575
|
+
Check_Type(val, T_FIXNUM);
|
576
|
+
|
577
|
+
/*
|
578
|
+
* strip object
|
579
|
+
*/
|
580
|
+
Data_Get_Struct(self, camera_t, ptr);
|
581
|
+
|
582
|
+
/*
|
583
|
+
* set parameter
|
584
|
+
*/
|
585
|
+
err = camera_set_image_width(ptr, FIX2INT(val));
|
586
|
+
if (err) {
|
587
|
+
rb_raise(rb_eRuntimeError, "set image width failed.");
|
588
|
+
}
|
589
|
+
|
590
|
+
return Qnil;
|
591
|
+
}
|
592
|
+
|
593
|
+
static VALUE
|
594
|
+
rb_camera_get_image_height(VALUE self)
|
595
|
+
{
|
596
|
+
int ret;
|
597
|
+
camera_t* ptr;
|
598
|
+
int err;
|
599
|
+
|
600
|
+
/*
|
601
|
+
* strip object
|
602
|
+
*/
|
603
|
+
Data_Get_Struct(self, camera_t, ptr);
|
604
|
+
|
605
|
+
/*
|
606
|
+
* get parameter
|
607
|
+
*/
|
608
|
+
err = camera_get_image_height(ptr, &ret);
|
609
|
+
if (err) {
|
610
|
+
rb_raise(rb_eRuntimeError, "get image height failed.");
|
611
|
+
}
|
612
|
+
|
613
|
+
return INT2FIX(ret);
|
614
|
+
}
|
615
|
+
|
616
|
+
static VALUE
|
617
|
+
rb_camera_set_image_height(VALUE self, VALUE val)
|
618
|
+
{
|
619
|
+
camera_t* ptr;
|
620
|
+
int err;
|
621
|
+
|
622
|
+
/*
|
623
|
+
* argument check
|
624
|
+
*/
|
625
|
+
Check_Type(val, T_FIXNUM);
|
626
|
+
|
627
|
+
/*
|
628
|
+
* strip object
|
629
|
+
*/
|
630
|
+
Data_Get_Struct(self, camera_t, ptr);
|
631
|
+
|
632
|
+
/*
|
633
|
+
* set parameter
|
634
|
+
*/
|
635
|
+
err = camera_set_image_height(ptr, FIX2INT(val));
|
636
|
+
if (err) {
|
637
|
+
rb_raise(rb_eRuntimeError, "set image height failed.");
|
638
|
+
}
|
639
|
+
|
640
|
+
return Qnil;
|
641
|
+
}
|
642
|
+
|
643
|
+
static VALUE
|
644
|
+
rb_camera_get_framerate(VALUE self)
|
645
|
+
{
|
646
|
+
return Qnil;
|
647
|
+
}
|
648
|
+
|
649
|
+
static VALUE
|
650
|
+
rb_camera_set_framerate(VALUE self, VALUE val)
|
651
|
+
{
|
652
|
+
camera_t* ptr;
|
653
|
+
int num;
|
654
|
+
int denom;
|
655
|
+
int err;
|
656
|
+
|
657
|
+
/*
|
658
|
+
* argument check
|
659
|
+
*/
|
660
|
+
switch (TYPE(val)) {
|
661
|
+
case T_FIXNUM:
|
662
|
+
num = 1;
|
663
|
+
denom = FIX2INT(val);
|
664
|
+
break;
|
665
|
+
|
666
|
+
case T_FLOAT:
|
667
|
+
num = 1000;
|
668
|
+
denom = (int)(NUM2DBL(val) * 1000.0);
|
669
|
+
break;
|
670
|
+
|
671
|
+
case T_RATIONAL:
|
672
|
+
num = FIX2INT(rb_rational_den(val));
|
673
|
+
denom = FIX2INT(rb_rational_num(val));
|
674
|
+
break;
|
675
|
+
|
676
|
+
default:
|
677
|
+
rb_raise(rb_eArgError, "illeagal framerate value.");
|
678
|
+
}
|
679
|
+
|
680
|
+
/*
|
681
|
+
* strip object
|
682
|
+
*/
|
683
|
+
Data_Get_Struct(self, camera_t, ptr);
|
684
|
+
|
685
|
+
/*
|
686
|
+
* set framerate
|
687
|
+
*/
|
688
|
+
err = camera_set_framerate(ptr, num, denom);
|
689
|
+
if (err) {
|
690
|
+
rb_raise(rb_eRuntimeError, "set framerate failed.");
|
691
|
+
}
|
692
|
+
|
693
|
+
return Qnil;
|
694
|
+
}
|
695
|
+
|
696
|
+
static VALUE
|
697
|
+
rb_camera_state( VALUE self)
|
698
|
+
{
|
699
|
+
camera_t* ptr;
|
700
|
+
const char* str;
|
701
|
+
|
702
|
+
/*
|
703
|
+
* strip object
|
704
|
+
*/
|
705
|
+
Data_Get_Struct(self, camera_t, ptr);
|
706
|
+
|
707
|
+
/*
|
708
|
+
* convert state code
|
709
|
+
*/
|
710
|
+
switch (ptr->state) {
|
711
|
+
case -1:
|
712
|
+
str = "ERROR";
|
713
|
+
break;
|
714
|
+
|
715
|
+
case 0:
|
716
|
+
str = "FINALIZED";
|
717
|
+
break;
|
718
|
+
|
719
|
+
case 1:
|
720
|
+
str = "INITIALIZED";
|
721
|
+
break;
|
722
|
+
|
723
|
+
case 2:
|
724
|
+
str = "PREAPARE";
|
725
|
+
break;
|
726
|
+
|
727
|
+
case 3:
|
728
|
+
str = "READY";
|
729
|
+
break;
|
730
|
+
|
731
|
+
case 4:
|
732
|
+
str = "ST_REQUESTED";
|
733
|
+
break;
|
734
|
+
|
735
|
+
default:
|
736
|
+
str = "unknown";
|
737
|
+
break;
|
738
|
+
}
|
739
|
+
|
740
|
+
return ID2SYM(rb_intern(str));
|
741
|
+
}
|
742
|
+
|
743
|
+
static VALUE
|
744
|
+
rb_camera_start(VALUE self)
|
745
|
+
{
|
746
|
+
int err;
|
747
|
+
camera_t* ptr;
|
748
|
+
|
749
|
+
/*
|
750
|
+
* strip object
|
751
|
+
*/
|
752
|
+
Data_Get_Struct(self, camera_t, ptr);
|
753
|
+
|
754
|
+
/*
|
755
|
+
* convert
|
756
|
+
*/
|
757
|
+
err = camera_start(ptr);
|
758
|
+
if (err) {
|
759
|
+
rb_raise(rb_eRuntimeError, "start capture failed.");
|
760
|
+
}
|
761
|
+
|
762
|
+
return Qnil;
|
763
|
+
}
|
764
|
+
|
765
|
+
static VALUE
|
766
|
+
rb_camera_stop(VALUE self)
|
767
|
+
{
|
768
|
+
int err;
|
769
|
+
camera_t* ptr;
|
770
|
+
|
771
|
+
/*
|
772
|
+
* strip object
|
773
|
+
*/
|
774
|
+
Data_Get_Struct(self, camera_t, ptr);
|
775
|
+
|
776
|
+
/*
|
777
|
+
* convert
|
778
|
+
*/
|
779
|
+
err = camera_stop(ptr);
|
780
|
+
if (err) {
|
781
|
+
rb_raise(rb_eRuntimeError, "stop capture failed.");
|
782
|
+
}
|
783
|
+
|
784
|
+
return Qnil;
|
785
|
+
}
|
786
|
+
|
787
|
+
|
788
|
+
static VALUE
|
789
|
+
rb_camera_capture(VALUE self)
|
790
|
+
{
|
791
|
+
VALUE ret;
|
792
|
+
camera_t* ptr;
|
793
|
+
size_t used;
|
794
|
+
int err;
|
795
|
+
|
796
|
+
/*
|
797
|
+
* strip object
|
798
|
+
*/
|
799
|
+
Data_Get_Struct(self, camera_t, ptr);
|
800
|
+
|
801
|
+
/*
|
802
|
+
* allocate return value.
|
803
|
+
*/
|
804
|
+
ret = rb_str_buf_new(ptr->image_size);
|
805
|
+
rb_str_set_len(ret, ptr->image_size);
|
806
|
+
|
807
|
+
/*
|
808
|
+
* do capture
|
809
|
+
*/
|
810
|
+
err = camera_get_image(ptr, RSTRING_PTR(ret), &used);
|
811
|
+
if (err) {
|
812
|
+
rb_raise(rb_eRuntimeError, "capture failed.");
|
813
|
+
}
|
814
|
+
|
815
|
+
if (ptr->image_size != used) {
|
816
|
+
rb_str_set_len(ret, used);
|
817
|
+
}
|
818
|
+
|
819
|
+
return ret;
|
820
|
+
}
|
821
|
+
|
822
|
+
static VALUE
|
823
|
+
rb_camera_is_busy(VALUE self)
|
824
|
+
{
|
825
|
+
camera_t* ptr;
|
826
|
+
int err;
|
827
|
+
int busy;
|
828
|
+
|
829
|
+
/*
|
830
|
+
* strip object
|
831
|
+
*/
|
832
|
+
Data_Get_Struct(self, camera_t, ptr);
|
833
|
+
|
834
|
+
/*
|
835
|
+
* do check
|
836
|
+
*/
|
837
|
+
err = camera_check_busy(ptr, &busy);
|
838
|
+
if (err) {
|
839
|
+
rb_raise(rb_eRuntimeError, "check failed.");
|
840
|
+
}
|
841
|
+
|
842
|
+
return (busy)? Qtrue: Qfalse;
|
843
|
+
}
|
844
|
+
|
845
|
+
static VALUE
|
846
|
+
rb_camera_is_error(VALUE self)
|
847
|
+
{
|
848
|
+
camera_t* ptr;
|
849
|
+
int err;
|
850
|
+
int error;
|
851
|
+
|
852
|
+
/*
|
853
|
+
* strip object
|
854
|
+
*/
|
855
|
+
Data_Get_Struct(self, camera_t, ptr);
|
856
|
+
|
857
|
+
/*
|
858
|
+
* do check
|
859
|
+
*/
|
860
|
+
err = camera_check_error(ptr, &error);
|
861
|
+
if (err) {
|
862
|
+
rb_raise(rb_eRuntimeError, "check failed.");
|
863
|
+
}
|
864
|
+
|
865
|
+
return (error)? Qtrue: Qfalse;
|
866
|
+
}
|
867
|
+
|
868
|
+
void
|
869
|
+
Init_v4l2()
|
870
|
+
{
|
871
|
+
rb_require("monitor");
|
872
|
+
|
873
|
+
module = rb_define_module("Video4Linux2");
|
874
|
+
camera_klass = rb_define_class_under(module, "Camera", rb_cObject);
|
875
|
+
|
876
|
+
rb_define_alloc_func(camera_klass, rb_camera_alloc);
|
877
|
+
rb_define_method(camera_klass, "initialize", rb_camera_initialize, 1);
|
878
|
+
rb_define_method(camera_klass, "close", rb_camera_close, 0);
|
879
|
+
rb_define_method(camera_klass, "controls", rb_camera_get_controls, 0);
|
880
|
+
rb_define_method(camera_klass,
|
881
|
+
"support_formats", rb_camera_get_support_formats, 0);
|
882
|
+
rb_define_method(camera_klass,
|
883
|
+
"frame_capabilities", rb_camera_get_frame_capabilities, 1);
|
884
|
+
rb_define_method(camera_klass, "set_control", rb_camera_set_control, 2);
|
885
|
+
rb_define_method(camera_klass, "get_control", rb_camera_get_control, 1);
|
886
|
+
rb_define_method(camera_klass, "format=", rb_camera_set_format, 1);
|
887
|
+
rb_define_method(camera_klass, "image_width", rb_camera_get_image_width, 0);
|
888
|
+
rb_define_method(camera_klass, "image_width=", rb_camera_set_image_width, 1);
|
889
|
+
rb_define_method(camera_klass, "image_height", rb_camera_get_image_height,0);
|
890
|
+
rb_define_method(camera_klass, "image_height=", rb_camera_set_image_height,1);
|
891
|
+
rb_define_method(camera_klass, "framerate", rb_camera_get_framerate, 0);
|
892
|
+
rb_define_method(camera_klass, "framerate=", rb_camera_set_framerate, 1);
|
893
|
+
rb_define_method(camera_klass, "state", rb_camera_state, 0);
|
894
|
+
rb_define_method(camera_klass, "start", rb_camera_start, 0);
|
895
|
+
rb_define_method(camera_klass, "stop", rb_camera_stop, 0);
|
896
|
+
rb_define_method(camera_klass, "capture", rb_camera_capture, 0);
|
897
|
+
rb_define_method(camera_klass, "busy?", rb_camera_is_busy, 0);
|
898
|
+
rb_define_method(camera_klass, "error?", rb_camera_is_error, 0);
|
899
|
+
|
900
|
+
rb_define_attr(camera_klass, "name", !0, 0);
|
901
|
+
rb_define_attr(camera_klass, "driver", !0, 0);
|
902
|
+
rb_define_attr(camera_klass, "bus", !0, 0);
|
903
|
+
|
904
|
+
rb_define_singleton_method( camera_klass, "open", rb_camera_open, 1);
|
905
|
+
|
906
|
+
control_klass = rb_define_class_under(camera_klass,
|
907
|
+
"Control", rb_cObject);
|
908
|
+
rb_define_attr(control_klass, "name", !0, 0);
|
909
|
+
rb_define_attr(control_klass, "id", !0, 0);
|
910
|
+
rb_define_attr(control_klass, "value", !0, 0);
|
911
|
+
|
912
|
+
integer_klass = rb_define_class_under(camera_klass,
|
913
|
+
"IntegerControl", control_klass);
|
914
|
+
rb_define_attr(integer_klass, "min", !0, 0);
|
915
|
+
rb_define_attr(integer_klass, "max", !0, 0);
|
916
|
+
rb_define_attr(integer_klass, "step", !0, 0);
|
917
|
+
rb_define_attr(integer_klass, "default", !0, 0);
|
918
|
+
|
919
|
+
boolean_klass = rb_define_class_under(camera_klass,
|
920
|
+
"BooleanControl", control_klass);
|
921
|
+
rb_define_attr(boolean_klass, "default", !0, 0);
|
922
|
+
|
923
|
+
menu_klass = rb_define_class_under(camera_klass,
|
924
|
+
"MenuControl", control_klass);
|
925
|
+
rb_define_attr(menu_klass, "default", !0, 0);
|
926
|
+
rb_define_attr(menu_klass, "items", !0, 0);
|
927
|
+
|
928
|
+
menu_item_klass = rb_define_class_under(camera_klass,
|
929
|
+
"MenuItem", rb_cObject);
|
930
|
+
rb_define_attr(menu_item_klass, "name", !0, 0);
|
931
|
+
rb_define_attr(menu_item_klass, "index", !0, 0);
|
932
|
+
|
933
|
+
frame_cap_klass = rb_define_class_under(camera_klass,
|
934
|
+
"FrameCapability", rb_cObject);
|
935
|
+
rb_define_attr(frame_cap_klass, "width", !0, 0);
|
936
|
+
rb_define_attr(frame_cap_klass, "height", !0, 0);
|
937
|
+
rb_define_attr(frame_cap_klass, "rate", !0, 0);
|
938
|
+
|
939
|
+
fmt_desc_klass = rb_define_class_under(camera_klass,
|
940
|
+
"FormatDescription", rb_cObject);
|
941
|
+
rb_define_attr(fmt_desc_klass, "fcc", !0, 0);
|
942
|
+
rb_define_attr(fmt_desc_klass, "description", !0, 0);
|
943
|
+
|
944
|
+
id_yuyv = rb_intern_const("YUYV");
|
945
|
+
id_yuv422 = rb_intern_const("YUV422");
|
946
|
+
id_nv12 = rb_intern_const("NV12");
|
947
|
+
id_nv21 = rb_intern_const("NV21");
|
948
|
+
id_nv16 = rb_intern_const("NV16");
|
949
|
+
id_rgb565 = rb_intern_const("RGB565");
|
950
|
+
id_mjpeg = rb_intern_const("MJPEG");
|
951
|
+
id_h264 = rb_intern_const("H264");
|
952
|
+
id_iv_name = rb_intern_const("@name");
|
953
|
+
id_iv_driver = rb_intern_const("@driver");
|
954
|
+
id_iv_bus = rb_intern_const("@bus");
|
955
|
+
id_iv_id = rb_intern_const("@id");
|
956
|
+
id_iv_min = rb_intern_const("@max");
|
957
|
+
id_iv_max = rb_intern_const("@min");
|
958
|
+
id_iv_step = rb_intern_const("@step");
|
959
|
+
id_iv_default = rb_intern_const("@default");
|
960
|
+
id_iv_items = rb_intern_const("@items");
|
961
|
+
id_iv_index = rb_intern_const("@index");
|
962
|
+
id_iv_width = rb_intern_const("@width");
|
963
|
+
id_iv_height = rb_intern_const("@height");
|
964
|
+
id_iv_rate = rb_intern_const("@rate");
|
965
|
+
id_iv_fcc = rb_intern_const("@fcc");
|
966
|
+
id_iv_desc = rb_intern_const("@description");
|
967
|
+
}
|