-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathcameractrls.py
executable file
·3084 lines (2663 loc) · 132 KB
/
cameractrls.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3
import ctypes, ctypes.util, logging, os.path, getopt, sys, subprocess, select, time, math, configparser
from fcntl import ioctl
from threading import Thread
ghurl = 'https://github.com/soyersoyer/cameractrls'
version = 'v0.6.7'
v4ldirs = {
'/dev/v4l/by-id/': '',
'/dev/v4l/by-path/': '',
'/dev/': 'video',
}
class Device:
def __init__(self, name, path, real_path, driver):
self.name = name
self.path = path
self.real_path = real_path
self.driver = driver
def _is_valid_operand(self, other):
return (hasattr(other, "name") and
hasattr(other, "path"))
def __lt__(self, other):
if not self._is_valid_operand(other):
return NotImplemented
return self.name < other.name
def __eq__(self, other):
if not self._is_valid_operand(other):
return NotImplemented
return self.path == other.path
def __str__(self):
return f'"{self.name}" at {self.path}{" -> " + self.real_path if self.real_path != self.path else ""}'
def get_devices(dirs):
devices = []
resolved_devices = []
for dir, prefix in dirs.items():
if not os.path.isdir(dir):
continue
for device in os.listdir(dir):
if not device.startswith(prefix):
continue
device = dir + device
resolved = device if not os.path.islink(device) else os.path.abspath(dir + os.readlink(device))
if resolved in resolved_devices:
continue
caps = get_device_capability(device)
if not(caps.device_caps & V4L2_CAP_VIDEO_CAPTURE):
continue
devices.append(Device(f'{str(caps.card, "utf-8")} ({resolved})', device, resolved, str(caps.driver)))
resolved_devices.append(resolved)
devices.sort()
return devices
ptz_hw_executables = [
f'{sys.path[0]}/cameraptzspnav.py',
f'{sys.path[0]}/cameraptzgame.py',
f'{sys.path[0]}/cameraptzmidi.py',
]
def exec_and_get_lines(params):
return subprocess.run(params, capture_output=True).stdout.splitlines()
def get_ptz_hw_controllers(executables):
controllers = []
for cmd in executables:
if not os.access(cmd, os.X_OK):
logging.warning(f'{cmd} is not an executable')
continue
controllers += [
PTZHWController(cmd, c.decode())
for c in exec_and_get_lines([cmd, '-l'])
]
return controllers
class PTZHWControllers():
def __init__(self, video_device, toggle_cb, notify_err, notify_end):
self.controllers = get_ptz_hw_controllers(ptz_hw_executables)
self.video_device = video_device
self.toggle_cb = toggle_cb
self.notify_err = notify_err
self.notify_end = notify_end
def get_names(self):
return [c.id for c in self.controllers]
def start(self, i):
c = self.controllers[i]
if c.is_running():
c.terminate()
p = c.run(self.video_device)
self.toggle_cb(self.check_ptz_open, p, i)
def stop(self, i):
c = self.controllers[i]
if c.is_running():
c.terminate()
def set_active(self, i, state):
if state:
self.start(i)
else:
self.stop(i)
def check_ptz_open(self, p, i):
# if process returned
if p.poll() is not None:
(stdout, stderr) = p.communicate()
errstr = stderr.decode()
sys.stderr.write(errstr)
if p.returncode != 0 and p.returncode != -15:
self.notify_err(errstr.strip())
self.notify_end(i)
# False removes the timeout
return False
return True
def terminate_all(self):
for c in self.controllers:
c.terminate()
class PTZHWController():
def __init__(self, command, id):
self.command = command
self.id = id
self.process = None
def run(self, video_device):
self.process = subprocess.Popen([self.command, '-c', self.id, '-d', video_device], stderr=subprocess.PIPE)
return self.process
def is_running(self):
return self.process and self.process.poll() is None
def terminate(self):
if self.process:
self.process.terminate()
# ioctl
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_NRSHIFT = 0
_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
_IOC_WRITE = 1
_IOC_READ = 2
def _IOC(dir_, type_, nr, size):
return (
ctypes.c_int32(dir_ << _IOC_DIRSHIFT).value |
ctypes.c_int32(ord(type_) << _IOC_TYPESHIFT).value |
ctypes.c_int32(nr << _IOC_NRSHIFT).value |
ctypes.c_int32(size << _IOC_SIZESHIFT).value)
def _IOC_TYPECHECK(t):
return ctypes.sizeof(t)
def _IOR(type_, nr, size):
return _IOC(_IOC_READ, type_, nr, _IOC_TYPECHECK(size))
def _IOW(type_, nr, size):
return _IOC(_IOC_WRITE, type_, nr, _IOC_TYPECHECK(size))
def _IOWR(type_, nr, size):
return _IOC(_IOC_READ | _IOC_WRITE, type_, nr, _IOC_TYPECHECK(size))
#
# ioctl structs, codes for UVC extensions
#
enum = ctypes.c_uint
class v4l2_capability(ctypes.Structure):
_fields_ = [
('driver', ctypes.c_char * 16),
('card', ctypes.c_char * 32),
('bus_info', ctypes.c_char * 32),
('version', ctypes.c_uint32),
('capabilities', ctypes.c_uint32),
('device_caps', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 3),
]
# streaming
VIDEO_MAX_PLANES = 8
v4l2_buf_type = enum
(V4L2_BUF_TYPE_VIDEO_CAPTURE) = list(range(1, 2))
v4l2_memory = enum
(V4L2_MEMORY_MMAP) = range(1, 2)
v4l2_field = enum
(V4L2_FIELD_ANY) = range(1)
v4l2_colorspace = enum
(
V4L2_COLORSPACE_DEFAULT,
V4L2_COLORSPACE_SMPTE170M,
V4L2_COLORSPACE_SMPTE240M,
V4L2_COLORSPACE_REC709,
V4L2_COLORSPACE_BT878,
V4L2_COLORSPACE_470_SYSTEM_M,
V4L2_COLORSPACE_470_SYSTEM_BG,
V4L2_COLORSPACE_JPEG,
V4L2_COLORSPACE_SRGB,
V4L2_COLORSPACE_OPRGB,
V4L2_COLORSPACE_BT2020,
V4L2_COLORSPACE_RAW,
V4L2_COLORSPACE_DCI_P3,
) = range(13)
V4L2_CAP_VIDEO_CAPTURE = 0x00000001
V4L2_CAP_STREAMING = 0x04000000
def v4l2_fourcc(a, b, c, d):
return ord(a) | (ord(b) << 8) | (ord(c) << 16) | (ord(d) << 24)
V4L2_PIX_FMT_YUYV = v4l2_fourcc('Y', 'U', 'Y', 'V')
V4L2_PIX_FMT_YVYU = v4l2_fourcc('Y', 'V', 'Y', 'U')
V4L2_PIX_FMT_UYVY = v4l2_fourcc('U', 'Y', 'V', 'Y')
V4L2_PIX_FMT_MJPEG = v4l2_fourcc('M', 'J', 'P', 'G')
V4L2_PIX_FMT_JPEG = v4l2_fourcc('J', 'P', 'E', 'G')
V4L2_PIX_FMT_NV12 = v4l2_fourcc('N', 'V', '1', '2')
V4L2_PIX_FMT_NV21 = v4l2_fourcc('N', 'V', '2', '1')
V4L2_PIX_FMT_YU12 = v4l2_fourcc('Y', 'U', '1', '2')
V4L2_PIX_FMT_YV12 = v4l2_fourcc('Y', 'V', '1', '2')
V4L2_PIX_FMT_GREY = v4l2_fourcc('G', 'R', 'E', 'Y')
V4L2_PIX_FMT_RGB565 = v4l2_fourcc('R', 'G', 'B', 'P')
V4L2_PIX_FMT_RGB24 = v4l2_fourcc('R', 'G', 'B', '3')
V4L2_PIX_FMT_BGR24 = v4l2_fourcc('B', 'G', 'R', '3')
V4L2_PIX_FMT_RX24 = v4l2_fourcc('R', 'X', '2', '4')
V4L2_BUF_TYPE_VIDEO_CAPTURE = 1
V4L2_MEMORY_MMAP = 1
class v4l2_fmtdesc(ctypes.Structure):
_fields_ = [
('index', ctypes.c_uint32),
('type', ctypes.c_int),
('flags', ctypes.c_uint32),
('description', ctypes.c_char * 32),
('pixelformat', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 4),
]
class v4l2_requestbuffers(ctypes.Structure):
_fields_ = [
('count', ctypes.c_uint32),
('type', v4l2_buf_type),
('memory', v4l2_memory),
('reserved', ctypes.c_uint32 * 2),
]
class v4l2_plane(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('mem_offset', ctypes.c_uint32),
('userptr', ctypes.c_ulong),
('fd', ctypes.c_int32),
]
_fields_ = [
('bytesused', ctypes.c_uint32),
('length', ctypes.c_uint32),
('m', _u),
('data_offset', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 11),
]
class v4l2_pix_format(ctypes.Structure):
_fields_ = [
('width', ctypes.c_uint32),
('height', ctypes.c_uint32),
('pixelformat', ctypes.c_uint32),
('field', v4l2_field),
('bytesperline', ctypes.c_uint32),
('sizeimage', ctypes.c_uint32),
('colorspace', v4l2_colorspace),
('priv', ctypes.c_uint32),
]
class v4l2_plane_pix_format(ctypes.Structure):
_fields_ = [
('sizeimage', ctypes.c_uint32),
('bytesperline', ctypes.c_uint32),
('reserved', ctypes.c_uint16 * 6),
]
_pack_ = True
class v4l2_pix_format_mplane(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('ycbcr_enc', ctypes.c_uint8),
('hsv_enc', ctypes.c_uint8),
]
_fields_ = [
('width', ctypes.c_uint32),
('height', ctypes.c_uint32),
('pixelformat', ctypes.c_uint32),
('field', v4l2_field),
('colorspace', v4l2_colorspace),
('plane_fmt', v4l2_plane_pix_format * VIDEO_MAX_PLANES),
('num_planes', ctypes.c_uint8),
('flags', ctypes.c_uint8),
('_u', _u),
('quantization', ctypes.c_uint8),
('xfer_func', ctypes.c_uint8),
('reserved', ctypes.c_uint8 * 7),
]
_anonymous_ = ('_u',)
_pack_ = True
class v4l2_rect(ctypes.Structure):
_fields_ = [
('left', ctypes.c_int32),
('top', ctypes.c_int32),
('width', ctypes.c_int32),
('height', ctypes.c_int32),
]
class v4l2_clip(ctypes.Structure):
pass
v4l2_clip._fields_ = [
('c', v4l2_rect),
('next', ctypes.POINTER(v4l2_clip)),
]
class v4l2_vbi_format(ctypes.Structure):
_fields_ = [
('sampling_rate', ctypes.c_uint32),
('offset', ctypes.c_uint32),
('samples_per_line', ctypes.c_uint32),
('sample_format', ctypes.c_uint32),
('start', ctypes.c_int32 * 2),
('count', ctypes.c_uint32 * 2),
('flags', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 2),
]
class v4l2_sliced_vbi_format(ctypes.Structure):
_fields_ = [
('service_set', ctypes.c_uint16),
('service_lines', ctypes.c_uint16 * 2 * 24),
('io_size', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 2),
]
class v4l2_window(ctypes.Structure):
_fields_ = [
('w', v4l2_rect),
('field', v4l2_field),
('chromakey', ctypes.c_uint32),
('clips', ctypes.POINTER(v4l2_clip)),
('clipcount', ctypes.c_uint32),
('bitmap', ctypes.c_void_p),
('global_alpha', ctypes.c_uint8),
]
class v4l2_format(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('pix', v4l2_pix_format),
('pix_mp', v4l2_pix_format_mplane),
('win', v4l2_window),
('vbi', v4l2_vbi_format),
('sliced', v4l2_sliced_vbi_format),
('raw_data', ctypes.c_char * 200),
]
_fields_ = [
('type', v4l2_buf_type),
('fmt', _u),
]
class timeval(ctypes.Structure):
_fields_ = [
('secs', ctypes.c_long),
('usecs', ctypes.c_long),
]
class v4l2_timecode(ctypes.Structure):
_fields_ = [
('type', ctypes.c_uint32),
('flags', ctypes.c_uint32),
('frames', ctypes.c_uint8),
('seconds', ctypes.c_uint8),
('minutes', ctypes.c_uint8),
('hours', ctypes.c_uint8),
('userbits', ctypes.c_uint8 * 4),
]
class v4l2_buffer(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('offset', ctypes.c_uint32),
('userptr', ctypes.c_ulong),
('planes', ctypes.POINTER(v4l2_plane)),
('fd', ctypes.c_int32),
]
_fields_ = [
('index', ctypes.c_uint32),
('type', v4l2_buf_type),
('bytesused', ctypes.c_uint32),
('flags', ctypes.c_uint32),
('field', v4l2_field),
('timestamp', timeval),
('timecode', v4l2_timecode),
('sequence', ctypes.c_uint32),
('memory', v4l2_memory),
('m', _u),
('length', ctypes.c_uint32),
('input', ctypes.c_uint32),
('reserved', ctypes.c_uint32),
]
v4l2_frmsizetypes = enum
(
V4L2_FRMSIZE_TYPE_DISCRETE,
V4L2_FRMSIZE_TYPE_CONTINUOUS,
V4L2_FRMSIZE_TYPE_STEPWISE,
) = range(1, 4)
class v4l2_frmsize_discrete(ctypes.Structure):
_fields_ = [
('width', ctypes.c_uint32),
('height', ctypes.c_uint32),
]
class v4l2_frmsize_stepwise(ctypes.Structure):
_fields_ = [
('min_width', ctypes.c_uint32),
('max_width', ctypes.c_uint32),
('step_width', ctypes.c_uint32),
('min_height', ctypes.c_uint32),
('max_height', ctypes.c_uint32),
('step_height', ctypes.c_uint32),
]
class v4l2_frmsizeenum(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('discrete', v4l2_frmsize_discrete),
('stepwise', v4l2_frmsize_stepwise),
]
_fields_ = [
('index', ctypes.c_uint32),
('pixel_format', ctypes.c_uint32),
('type', ctypes.c_uint32),
('_u', _u),
('reserved', ctypes.c_uint32 * 2)
]
_anonymous_ = ('_u',)
class v4l2_fract(ctypes.Structure):
_fields_ = [
('numerator', ctypes.c_uint32),
('denominator', ctypes.c_uint32),
]
v4l2_frmivaltypes = enum
(
V4L2_FRMIVAL_TYPE_DISCRETE,
V4L2_FRMIVAL_TYPE_CONTINUOUS,
V4L2_FRMIVAL_TYPE_STEPWISE,
) = range(1, 4)
class v4l2_frmival_stepwise(ctypes.Structure):
_fields_ = [
('min', v4l2_fract),
('max', v4l2_fract),
('step', v4l2_fract),
]
class v4l2_frmivalenum(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('discrete', v4l2_fract),
('stepwise', v4l2_frmival_stepwise),
]
_fields_ = [
('index', ctypes.c_uint32),
('pixel_format', ctypes.c_uint32),
('width', ctypes.c_uint32),
('height', ctypes.c_uint32),
('type', ctypes.c_uint32),
('_u', _u),
('reserved', ctypes.c_uint32 * 2),
]
_anonymous_ = ('_u',)
class v4l2_captureparm(ctypes.Structure):
_fields_ = [
('capability', ctypes.c_uint32),
('capturemode', ctypes.c_uint32),
('timeperframe', v4l2_fract),
('extendedmode', ctypes.c_uint32),
('readbuffers', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 4),
]
V4L2_MODE_HIGHQUALITY = 0x0001
V4L2_CAP_TIMEPERFRAME = 0x1000
class v4l2_outputparm(ctypes.Structure):
_fields_ = [
('capability', ctypes.c_uint32),
('outputmode', ctypes.c_uint32),
('timeperframe', v4l2_fract),
('extendedmode', ctypes.c_uint32),
('writebuffers', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 4),
]
class v4l2_streamparm(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('capture', v4l2_captureparm),
('output', v4l2_outputparm),
('raw_data', ctypes.c_char * 200),
]
_fields_ = [
('type', v4l2_buf_type),
('parm', _u)
]
VIDIOC_ENUM_FMT = _IOWR('V', 2, v4l2_fmtdesc)
VIDIOC_G_FMT = _IOWR('V', 4, v4l2_format)
VIDIOC_S_FMT = _IOWR('V', 5, v4l2_format)
VIDIOC_REQBUFS = _IOWR('V', 8, v4l2_requestbuffers)
VIDIOC_QUERYBUF = _IOWR('V', 9, v4l2_buffer)
VIDIOC_QBUF = _IOWR('V', 15, v4l2_buffer)
VIDIOC_DQBUF = _IOWR('V', 17, v4l2_buffer)
VIDIOC_STREAMON = _IOW('V', 18, ctypes.c_int)
VIDIOC_STREAMOFF = _IOW('V', 19, ctypes.c_int)
VIDIOC_G_PARM = _IOWR('V', 21, v4l2_streamparm)
VIDIOC_S_PARM = _IOWR('V', 22, v4l2_streamparm)
VIDIOC_ENUM_FRAMESIZES = _IOWR('V', 74, v4l2_frmsizeenum)
VIDIOC_ENUM_FRAMEINTERVALS = _IOWR('V', 75, v4l2_frmivalenum)
# controls
v4l2_ctrl_type = enum
(
V4L2_CTRL_TYPE_INTEGER,
V4L2_CTRL_TYPE_BOOLEAN,
V4L2_CTRL_TYPE_MENU,
V4L2_CTRL_TYPE_BUTTON,
V4L2_CTRL_TYPE_INTEGER64,
V4L2_CTRL_TYPE_CTRL_CLASS,
V4L2_CTRL_TYPE_STRING,
V4L2_CTRL_TYPE_BITMASK,
V4L2_CTRL_TYPE_INTEGER_MENU,
) = range(1, 10)
V4L2_CTRL_FLAG_READ_ONLY = 0x0004
V4L2_CTRL_FLAG_UPDATE = 0x0008
V4L2_CTRL_FLAG_INACTIVE = 0x0010
V4L2_CTRL_FLAG_NEXT_CTRL = 0x80000000
V4L2_CTRL_FLAG_NEXT_COMPOUND = 0x40000000
V4L2_CTRL_CLASS_MASK = 0x00ff0000
V4L2_CTRL_CLASS_USER = 0x00980000
V4L2_CTRL_CLASS_CODEC = 0x00990000
V4L2_CTRL_CLASS_CAMERA = 0x009a0000
V4L2_CTRL_CLASS_JPEG = 0x009d0000
V4L2_CTRL_CLASS_IMAGE_SOURCE = 0x9e0000
V4L2_CTRL_CLASS_IMAGE_PROC = 0x9f0000
V4L2_CID_BASE = V4L2_CTRL_CLASS_USER | 0x900
V4L2_CID_BRIGHTNESS = V4L2_CID_BASE + 0
V4L2_CID_CONTRAST = V4L2_CID_BASE + 1
V4L2_CID_SATURATION = V4L2_CID_BASE + 2
V4L2_CID_HUE = V4L2_CID_BASE + 3
V4L2_CID_AUTO_WHITE_BALANCE = V4L2_CID_BASE + 12
V4L2_CID_DO_WHITE_BALANCE = V4L2_CID_BASE + 13
V4L2_CID_RED_BALANCE = V4L2_CID_BASE + 14
V4L2_CID_BLUE_BALANCE = V4L2_CID_BASE + 15
V4L2_CID_GAMMA = V4L2_CID_BASE + 16
V4L2_CID_EXPOSURE = V4L2_CID_BASE + 17
V4L2_CID_AUTOGAIN = V4L2_CID_BASE + 18
V4L2_CID_GAIN = V4L2_CID_BASE + 19
V4L2_CID_HFLIP = V4L2_CID_BASE + 20
V4L2_CID_VFLIP = V4L2_CID_BASE + 21
V4L2_CID_POWER_LINE_FREQUENCY = V4L2_CID_BASE + 24
V4L2_CID_HUE_AUTO = V4L2_CID_BASE + 25
V4L2_CID_WHITE_BALANCE_TEMPERATURE = V4L2_CID_BASE + 26
V4L2_CID_SHARPNESS = V4L2_CID_BASE + 27
V4L2_CID_BACKLIGHT_COMPENSATION = V4L2_CID_BASE + 28
V4L2_CID_CHROMA_AGC = V4L2_CID_BASE + 29
V4L2_CID_COLOR_KILLER = V4L2_CID_BASE + 30
V4L2_CID_COLORFX = V4L2_CID_BASE + 31
V4L2_CID_AUTOBRIGHTNESS = V4L2_CID_BASE + 32
V4L2_CID_BAND_STOP_FILTER = V4L2_CID_BASE + 33
V4L2_CID_ROTATE = V4L2_CID_BASE + 34
V4L2_CID_BG_COLOR = V4L2_CID_BASE + 35
V4L2_CID_CHROMA_GAIN = V4L2_CID_BASE + 36
V4L2_CID_ILLUMINATORS_1 = V4L2_CID_BASE + 37
V4L2_CID_ILLUMINATORS_2 = V4L2_CID_BASE + 38
V4L2_CID_ALPHA_COMPONENT = V4L2_CID_BASE + 41
V4L2_CID_COLORFX_CBCR = V4L2_CID_BASE + 42
V4L2_CID_COLORFX_RGB = V4L2_CID_BASE + 43
V4L2_CID_CODEC_BASE = V4L2_CTRL_CLASS_CODEC | 0x900
V4L2_CID_CAMERA_CLASS_BASE = V4L2_CTRL_CLASS_CAMERA | 0x900
V4L2_CID_EXPOSURE_AUTO = V4L2_CID_CAMERA_CLASS_BASE + 1
V4L2_CID_EXPOSURE_ABSOLUTE = V4L2_CID_CAMERA_CLASS_BASE + 2
V4L2_CID_EXPOSURE_AUTO_PRIORITY = V4L2_CID_CAMERA_CLASS_BASE + 3
V4L2_CID_PAN_RELATIVE = V4L2_CID_CAMERA_CLASS_BASE + 4
V4L2_CID_TILT_RELATIVE = V4L2_CID_CAMERA_CLASS_BASE + 5
V4L2_CID_PAN_RESET = V4L2_CID_CAMERA_CLASS_BASE + 6
V4L2_CID_TILT_RESET = V4L2_CID_CAMERA_CLASS_BASE + 7
V4L2_CID_PAN_ABSOLUTE = V4L2_CID_CAMERA_CLASS_BASE + 8
V4L2_CID_TILT_ABSOLUTE = V4L2_CID_CAMERA_CLASS_BASE + 9
V4L2_CID_FOCUS_ABSOLUTE = V4L2_CID_CAMERA_CLASS_BASE + 10
V4L2_CID_FOCUS_RELATIVE = V4L2_CID_CAMERA_CLASS_BASE + 11
V4L2_CID_FOCUS_AUTO = V4L2_CID_CAMERA_CLASS_BASE + 12
V4L2_CID_ZOOM_ABSOLUTE = V4L2_CID_CAMERA_CLASS_BASE + 13
V4L2_CID_ZOOM_RELATIVE = V4L2_CID_CAMERA_CLASS_BASE + 14
V4L2_CID_ZOOM_CONTINUOUS = V4L2_CID_CAMERA_CLASS_BASE + 15
V4L2_CID_PRIVACY = V4L2_CID_CAMERA_CLASS_BASE + 16
V4L2_CID_IRIS_ABSOLUTE = V4L2_CID_CAMERA_CLASS_BASE + 17
V4L2_CID_IRIS_RELATIVE = V4L2_CID_CAMERA_CLASS_BASE + 18
V4L2_CID_AUTO_EXPOSURE_BIAS = V4L2_CID_CAMERA_CLASS_BASE + 19
V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE = V4L2_CID_CAMERA_CLASS_BASE + 20
V4L2_CID_WIDE_DYNAMIC_RANGE = V4L2_CID_CAMERA_CLASS_BASE + 21
V4L2_CID_IMAGE_STABILIZATION = V4L2_CID_CAMERA_CLASS_BASE + 22
V4L2_CID_ISO_SENSITIVITY = V4L2_CID_CAMERA_CLASS_BASE + 23
V4L2_CID_ISO_SENSITIVITY_AUTO = V4L2_CID_CAMERA_CLASS_BASE + 24
V4L2_CID_EXPOSURE_METERING = V4L2_CID_CAMERA_CLASS_BASE + 25
V4L2_CID_SCENE_MODE = V4L2_CID_CAMERA_CLASS_BASE + 26
V4L2_CID_3A_LOCK = V4L2_CID_CAMERA_CLASS_BASE + 27
V4L2_CID_AUTO_FOCUS_START = V4L2_CID_CAMERA_CLASS_BASE + 28
V4L2_CID_AUTO_FOCUS_STOP = V4L2_CID_CAMERA_CLASS_BASE + 29
V4L2_CID_AUTO_FOCUS_STATUS = V4L2_CID_CAMERA_CLASS_BASE + 30
V4L2_CID_AUTO_FOCUS_RANGE = V4L2_CID_CAMERA_CLASS_BASE + 31
V4L2_CID_PAN_SPEED = V4L2_CID_CAMERA_CLASS_BASE + 32
V4L2_CID_TILT_SPEED = V4L2_CID_CAMERA_CLASS_BASE + 33
V4L2_CID_CAMERA_ORIENTATION = V4L2_CID_CAMERA_CLASS_BASE + 34
V4L2_CID_CAMERA_SENSOR_ROTATION = V4L2_CID_CAMERA_CLASS_BASE + 35
V4L2_CID_HDR_SENSOR_MODE = V4L2_CID_CAMERA_CLASS_BASE + 36
V4L2_CID_JPEG_CLASS_BASE = V4L2_CTRL_CLASS_JPEG | 0x900
V4L2_CID_JPEG_CHROMA_SUBSAMPLING = V4L2_CID_JPEG_CLASS_BASE + 1
V4L2_CID_JPEG_RESTART_INTERVAL = V4L2_CID_JPEG_CLASS_BASE + 2
V4L2_CID_JPEG_COMPRESSION_QUALITY = V4L2_CID_JPEG_CLASS_BASE + 3
V4L2_CID_JPEG_ACTIVE_MARKER = V4L2_CID_JPEG_CLASS_BASE + 4
V4L2_CID_IMAGE_SOURCE_CLASS_BASE = V4L2_CTRL_CLASS_IMAGE_SOURCE | 0x900
V4L2_CID_VBLANK = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 1
V4L2_CID_HBLANK = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 2
V4L2_CID_ANALOGUE_GAIN = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 3
V4L2_CID_TEST_PATTERN_RED = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 4
V4L2_CID_TEST_PATTERN_GREENR = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 5
V4L2_CID_TEST_PATTERN_BLUE = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 6
V4L2_CID_TEST_PATTERN_GREENB = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 7
V4L2_CID_UNIT_CELL_SIZE = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 8
V4L2_CID_NOTIFY_GAINS = V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 9
V4L2_CID_IMAGE_PROC_CLASS_BASE = V4L2_CTRL_CLASS_IMAGE_PROC | 0x900
V4L2_CID_LINK_FREQ = V4L2_CID_IMAGE_PROC_CLASS_BASE + 1
V4L2_CID_PIXEL_RATE = V4L2_CID_IMAGE_PROC_CLASS_BASE + 2
V4L2_CID_TEST_PATTERN = V4L2_CID_IMAGE_PROC_CLASS_BASE + 3
V4L2_CID_DEINTERLACING_MODE = V4L2_CID_IMAGE_PROC_CLASS_BASE + 4
V4L2_CID_DIGITAL_GAIN = V4L2_CID_IMAGE_PROC_CLASS_BASE + 5
# controls value should be zero after releasing mouse button
V4L2_CTRL_ZEROERS = [
V4L2_CID_PAN_SPEED,
V4L2_CID_TILT_SPEED,
V4L2_CID_ZOOM_CONTINUOUS,
]
V4L2_CTRL_INFO = {
V4L2_CID_BRIGHTNESS: ('V4L2_CID_BRIGHTNESS', 'Picture brightness, or more precisely, the black level.'),
V4L2_CID_CONTRAST: ('V4L2_CID_CONTRAST', 'Picture contrast or luma gain.'),
V4L2_CID_SATURATION: ('V4L2_CID_SATURATION', 'Picture color saturation or chroma gain.'),
V4L2_CID_HUE: ('V4L2_CID_HUE', 'Hue or color balance.'),
V4L2_CID_AUTO_WHITE_BALANCE: ('V4L2_CID_AUTO_WHITE_BALANCE', 'Automatic white balance.'),
V4L2_CID_DO_WHITE_BALANCE: ('V4L2_CID_DO_WHITE_BALANCE', 'This is an action control. When set (the value is ignored), the device will do a white balance and then hold the current setting. Contrast this with the boolean V4L2_CID_AUTO_WHITE_BALANCE, which, when activated, keeps adjusting the white balance.'),
V4L2_CID_RED_BALANCE: ('V4L2_CID_RED_BALANCE', 'Red chroma balance.'),
V4L2_CID_BLUE_BALANCE: ('V4L2_CID_BLUE_BALANCE', 'Blue chroma balance.'),
V4L2_CID_GAMMA: ('V4L2_CID_GAMMA', 'Gamma adjust.'),
V4L2_CID_EXPOSURE: ('V4L2_CID_EXPOSURE', 'Exposure.'),
V4L2_CID_AUTOGAIN: ('V4L2_CID_AUTOGAIN', 'Automatic gain/exposure control.'),
V4L2_CID_GAIN: ('V4L2_CID_GAIN', 'Gain control.'),
V4L2_CID_HFLIP: ('V4L2_CID_HFLIP', 'Mirror the picture horizontally.'),
V4L2_CID_VFLIP: ('V4L2_CID_VFLIP', 'Mirror the picture vertically.'),
V4L2_CID_POWER_LINE_FREQUENCY: ('V4L2_CID_POWER_LINE_FREQUENCY', 'Enables a power line frequency filter to avoid flicker.'),
V4L2_CID_HUE_AUTO: ('V4L2_CID_HUE_AUTO', 'Enables automatic hue control by the device. The effect of setting V4L2_CID_HUE while automatic hue control is enabled is undefined, drivers should ignore such request.'),
V4L2_CID_WHITE_BALANCE_TEMPERATURE: ('V4L2_CID_WHITE_BALANCE_TEMPERATURE', 'This control specifies the white balance settings as a color temperature in Kelvin. A driver should have a minimum of 2800 (incandescent) to 6500 (daylight).'),
V4L2_CID_SHARPNESS: ('V4L2_CID_SHARPNESS', 'Adjusts the sharpness filters in a camera. The minimum value disables the filters, higher values give a sharper picture.'),
V4L2_CID_BACKLIGHT_COMPENSATION: ('V4L2_CID_BACKLIGHT_COMPENSATION', 'Adjusts the backlight compensation in a camera. The minimum value disables backlight compensation.'),
V4L2_CID_CHROMA_AGC: ('V4L2_CID_CHROMA_AGC', 'Chroma automatic gain control.'),
V4L2_CID_CHROMA_GAIN: ('V4L2_CID_CHROMA_GAIN', 'Adjusts the Chroma gain control (for use when chroma AGC is disabled).'),
V4L2_CID_COLOR_KILLER: ('V4L2_CID_COLOR_KILLER', 'Enable the color killer (i. e. force a black & white image in case of a weak video signal).'),
V4L2_CID_COLORFX: ('V4L2_CID_COLORFX', 'Selects a color effect.'),
V4L2_CID_AUTOBRIGHTNESS: ('V4L2_CID_AUTOBRIGHTNESS', 'Enable Automatic Brightness.'),
V4L2_CID_BAND_STOP_FILTER: ('V4L2_CID_BAND_STOP_FILTER', 'Switch the band-stop filter of a camera sensor on or off, or specify its strength. Such band-stop filters can be used, for example, to filter out the fluorescent light component.'),
V4L2_CID_ROTATE: ('V4L2_CID_ROTATE', 'Rotates the image by specified angle. Common angles are 90, 270 and 180. Rotating the image to 90 and 270 will reverse the height and width of the display window. It is necessary to set the new height and width of the picture using the VIDIOC_S_FMT ioctl according to the rotation angle selected'),
V4L2_CID_BG_COLOR: ('V4L2_CID_BG_COLOR', 'Sets the background color on the current output device. Background color needs to be specified in the RGB24 format. The supplied 32 bit value is interpreted as bits 0-7 Red color information, bits 8-15 Green color information, bits 16-23 Blue color information and bits 24-31 must be zero.'),
V4L2_CID_ILLUMINATORS_1: ('V4L2_CID_ILLUMINATORS_1', 'Switch on or off the illuminator 1 of the device (usually a microscope).'),
V4L2_CID_ILLUMINATORS_2: ('V4L2_CID_ILLUMINATORS_2', 'Switch on or off the illuminator 2 of the device (usually a microscope).'),
V4L2_CID_ALPHA_COMPONENT: ('V4L2_CID_ALPHA_COMPONENT', 'Sets the alpha color component. When a capture device (or capture queue of a mem-to-mem device) produces a frame format that includes an alpha component (e.g. packed RGB image formats) and the alpha value is not defined by the device or the mem-to-mem input data this control lets you select the alpha component value of all pixels. When an output device (or output queue of a mem-to-mem device) consumes a frame format that doesn’t include an alpha component and the device supports alpha channel processing this control lets you set the alpha component value of all pixels for further processing in the device.'),
V4L2_CID_COLORFX_CBCR: ('V4L2_CID_COLORFX_CBCR', 'Determines the Cb and Cr coefficients for V4L2_COLORFX_SET_CBCR color effect. Bits [7:0] of the supplied 32 bit value are interpreted as Cr component, bits [15:8] as Cb component and bits [31:16] must be zero.'),
V4L2_CID_COLORFX_RGB: ('V4L2_CID_COLORFX_RGB', 'Determines the Red, Green, and Blue coefficients for V4L2_COLORFX_SET_RGB color effect. Bits [7:0] of the supplied 32 bit value are interpreted as Blue component, bits [15:8] as Green component, bits [23:16] as Red component, and bits [31:24] must be zero.'),
V4L2_CID_EXPOSURE_AUTO: ('V4L2_CID_EXPOSURE_AUTO', 'Enables automatic adjustments of the exposure time and/or iris aperture. The effect of manual changes of the exposure time or iris aperture while these features are enabled is undefined, drivers should ignore such requests. Possible values are: AUTO: Automatic exposure time, automatic iris aperture. MANUAL: Manual exposure time, manual iris. SHUTTER_PRIORITY: Manual exposure time, auto iris. APERTURE_PRIORITY: Auto exposure time, manual iris.'),
V4L2_CID_EXPOSURE_ABSOLUTE: ('V4L2_CID_EXPOSURE_ABSOLUTE', 'Determines the exposure time of the camera sensor. The exposure time is limited by the frame interval. Drivers should interpret the values as 100 µs units, where the value 1 stands for 1/10000th of a second, 10000 for 1 second and 100000 for 10 seconds.'),
V4L2_CID_EXPOSURE_AUTO_PRIORITY: ('V4L2_CID_EXPOSURE_AUTO_PRIORITY', 'When V4L2_CID_EXPOSURE_AUTO is set to AUTO or APERTURE_PRIORITY, this control determines if the device may dynamically vary the frame rate. By default this feature is disabled (0) and the frame rate must remain constant.'),
V4L2_CID_PAN_RELATIVE: ('V4L2_CID_PAN_RELATIVE', 'This control turns the camera horizontally by the specified amount. The unit is undefined. A positive value moves the camera to the right (clockwise when viewed from above), a negative value to the left. A value of zero does not cause motion. This is a write-only control.'),
V4L2_CID_TILT_RELATIVE: ('V4L2_CID_TILT_RELATIVE', 'This control turns the camera vertically by the specified amount. The unit is undefined. A positive value moves the camera up, a negative value down. A value of zero does not cause motion. This is a write-only control.'),
V4L2_CID_PAN_RESET: ('V4L2_CID_PAN_RESET', 'When this control is set, the camera moves horizontally to the default position.'),
V4L2_CID_TILT_RESET: ('V4L2_CID_TILT_RESET', 'When this control is set, the camera moves vertically to the default position.'),
V4L2_CID_PAN_ABSOLUTE: ('V4L2_CID_PAN_ABSOLUTE', 'This control turns the camera horizontally to the specified position. Positive values move the camera to the right (clockwise when viewed from above), negative values to the left. Drivers should interpret the values as arc seconds, with valid values between -180 * 3600 and +180 * 3600 inclusive.'),
V4L2_CID_TILT_ABSOLUTE: ('V4L2_CID_TILT_ABSOLUTE', 'This control turns the camera vertically to the specified position. Positive values move the camera up, negative values down. Drivers should interpret the values as arc seconds, with valid values between -180 * 3600 and +180 * 3600 inclusive.'),
V4L2_CID_FOCUS_ABSOLUTE: ('V4L2_CID_FOCUS_ABSOLUTE', 'This control sets the focal point of the camera to the specified position. The unit is undefined. Positive values set the focus closer to the camera, negative values towards infinity.'),
V4L2_CID_FOCUS_RELATIVE: ('V4L2_CID_FOCUS_RELATIVE', 'This control moves the focal point of the camera by the specified amount. The unit is undefined. Positive values move the focus closer to the camera, negative values towards infinity. This is a write-only control.'),
V4L2_CID_FOCUS_AUTO: ('V4L2_CID_FOCUS_AUTO', 'Enables continuous automatic focus adjustments. The effect of manual focus adjustments while this feature is enabled is undefined, drivers should ignore such requests.'),
V4L2_CID_ZOOM_ABSOLUTE: ('V4L2_CID_ZOOM_ABSOLUTE', 'Specify the objective lens focal length as an absolute value. The zoom unit is driver-specific and its value should be a positive integer.'),
V4L2_CID_ZOOM_RELATIVE: ('V4L2_CID_ZOOM_RELATIVE', 'Specify the objective lens focal length relatively to the current value. Positive values move the zoom lens group towards the telephoto direction, negative values towards the wide-angle direction. The zoom unit is driver-specific. This is a write-only control.'),
V4L2_CID_ZOOM_CONTINUOUS: ('V4L2_CID_ZOOM_CONTINUOUS', 'Move the objective lens group at the specified speed until it reaches physical device limits or until an explicit request to stop the movement. A positive value moves the zoom lens group towards the telephoto direction. A value of zero stops the zoom lens group movement. A negative value moves the zoom lens group towards the wide-angle direction. The zoom speed unit is driver-specific.'),
V4L2_CID_PRIVACY: ('V4L2_CID_PRIVACY', 'Prevent video from being acquired by the camera. When this control is set to TRUE (1), no image can be captured by the camera. Common means to enforce privacy are mechanical obturation of the sensor and firmware image processing, but the device is not restricted to these methods. Devices that implement the privacy control must support read access and may support write access.'),
V4L2_CID_IRIS_ABSOLUTE: ('V4L2_CID_IRIS_ABSOLUTE', 'This control sets the camera’s aperture to the specified value. The unit is undefined. Larger values open the iris wider, smaller values close it.'),
V4L2_CID_IRIS_RELATIVE: ('V4L2_CID_IRIS_RELATIVE', 'This control modifies the camera’s aperture by the specified amount. The unit is undefined. Positive values open the iris one step further, negative values close it one step further. This is a write-only control.'),
V4L2_CID_AUTO_EXPOSURE_BIAS: ('V4L2_CID_AUTO_EXPOSURE_BIAS', 'Determines the automatic exposure compensation, it is effective only when V4L2_CID_EXPOSURE_AUTO control is set to AUTO, SHUTTER_PRIORITY or APERTURE_PRIORITY. It is expressed in terms of EV, drivers should interpret the values as 0.001 EV units, where the value 1000 stands for +1 EV. Increasing the exposure compensation value is equivalent to decreasing the exposure value (EV) and will increase the amount of light at the image sensor. The camera performs the exposure compensation by adjusting absolute exposure time and/or aperture.'),
V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: ('V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE', 'Sets white balance to automatic, manual or a preset. The presets determine color temperature of the light as a hint to the camera for white balance adjustments resulting in most accurate color representation. The following white balance presets are listed in order of increasing color temperature.'),
V4L2_CID_WIDE_DYNAMIC_RANGE: ('V4L2_CID_WIDE_DYNAMIC_RANGE', 'Enables or disables the camera’s wide dynamic range feature. This feature allows to obtain clear images in situations where intensity of the illumination varies significantly throughout the scene, i.e. there are simultaneously very dark and very bright areas. It is most commonly realized in cameras by combining two subsequent frames with different exposure times.'),
V4L2_CID_IMAGE_STABILIZATION: ('V4L2_CID_IMAGE_STABILIZATION', 'Enables or disables image stabilization.'),
V4L2_CID_ISO_SENSITIVITY: ('V4L2_CID_ISO_SENSITIVITY', 'Determines ISO equivalent of an image sensor indicating the sensor’s sensitivity to light. The numbers are expressed in arithmetic scale, as per ISO 12232:2006 standard, where doubling the sensor sensitivity is represented by doubling the numerical ISO value. Applications should interpret the values as standard ISO values multiplied by 1000, e.g. control value 800 stands for ISO 0.8. Drivers will usually support only a subset of standard ISO values. The effect of setting this control while the V4L2_CID_ISO_SENSITIVITY_AUTO control is set to a value other than V4L2_CID_ISO_SENSITIVITY_MANUAL is undefined, drivers should ignore such requests.'),
V4L2_CID_ISO_SENSITIVITY_AUTO: ('V4L2_CID_ISO_SENSITIVITY_AUTO', 'Enables or disables automatic ISO sensitivity adjustments.'),
V4L2_CID_EXPOSURE_METERING: ('V4L2_CID_EXPOSURE_METERING', 'Determines how the camera measures the amount of light available for the frame exposure. Possible values are:'),
V4L2_CID_SCENE_MODE: ('V4L2_CID_SCENE_MODE', 'This control allows to select scene programs as the camera automatic modes optimized for common shooting scenes. Within these modes the camera determines best exposure, aperture, focusing, light metering, white balance and equivalent sensitivity. The controls of those parameters are influenced by the scene mode control. An exact behavior in each mode is subject to the camera specification. When the scene mode feature is not used, this control should be set to V4L2_SCENE_MODE_NONE to make sure the other possibly related controls are accessible.'),
V4L2_CID_3A_LOCK: ('V4L2_CID_3A_LOCK', 'This control locks or unlocks the automatic focus, exposure and white balance. The automatic adjustments can be paused independently by setting the corresponding lock bit to 1. The camera then retains the settings until the lock bit is cleared. The following lock bits are defined: When a given algorithm is not enabled, drivers should ignore requests to lock it and should return no error. An example might be an application setting bit V4L2_LOCK_WHITE_BALANCE when the V4L2_CID_AUTO_WHITE_BALANCE control is set to FALSE. The value of this control may be changed by exposure, white balance or focus controls'),
V4L2_CID_AUTO_FOCUS_START: ('V4L2_CID_AUTO_FOCUS_START', 'Starts single auto focus process. The effect of setting this control when V4L2_CID_FOCUS_AUTO is set to TRUE (1) is undefined, drivers should ignore such requests.'),
V4L2_CID_AUTO_FOCUS_STOP: ('V4L2_CID_AUTO_FOCUS_STOP', 'Aborts automatic focusing started with V4L2_CID_AUTO_FOCUS_START control. It is effective only when the continuous autofocus is disabled, that is when V4L2_CID_FOCUS_AUTO control is set to FALSE (0)'),
V4L2_CID_AUTO_FOCUS_STATUS: ('V4L2_CID_AUTO_FOCUS_STATUS', 'The automatic focus status. This is a read-only control.'),
V4L2_CID_AUTO_FOCUS_RANGE: ('V4L2_CID_AUTO_FOCUS_RANGE', 'Determines auto focus distance range for which lens may be adjusted.'),
V4L2_CID_PAN_SPEED: ('V4L2_CID_PAN_SPEED', 'This control turns the camera horizontally at the specific speed. The unit is undefined. A positive value moves the camera to the right (clockwise when viewed from above), a negative value to the left. A value of zero stops the motion if one is in progress and has no effect otherwise.'),
V4L2_CID_TILT_SPEED: ('V4L2_CID_TILT_SPEED', 'This control turns the camera vertically at the specified speed. The unit is undefined. A positive value moves the camera up, a negative value down. A value of zero stops the motion if one is in progress and has no effect otherwise.'),
V4L2_CID_CAMERA_ORIENTATION: ('V4L2_CID_CAMERA_ORIENTATION', 'his read-only control describes the camera orientation by reporting its mounting position on the device where the camera is installed. The control value is constant and not modifiable by software. This control is particularly meaningful for devices which have a well defined orientation, such as phones, laptops and portable devices since the control is expressed as a position relative to the device’s intended usage orientation. For example, a camera installed on the user-facing side of a phone, a tablet or a laptop device is said to be have V4L2_CAMERA_ORIENTATION_FRONT orientation, while a camera installed on the opposite side of the front one is said to be have V4L2_CAMERA_ORIENTATION_BACK orientation. Camera sensors not directly attached to the device, or attached in a way that allows them to move freely, such as webcams and digital cameras, are said to have the V4L2_CAMERA_ORIENTATION_EXTERNAL orientation.'),
V4L2_CID_CAMERA_SENSOR_ROTATION: ('V4L2_CID_CAMERA_SENSOR_ROTATION', 'This read-only control describes the rotation correction in degrees in the counter-clockwise direction to be applied to the captured images once captured to memory to compensate for the camera sensor mounting rotation.'),
V4L2_CID_HDR_SENSOR_MODE : ('V4L2_CID_HDR_SENSOR_MODE', 'Change the sensor HDR mode. A HDR picture is obtained by merging two captures of the same scene using two different exposure periods. HDR mode describes the way these two captures are merged in the sensor. As modes differ for each sensor, menu items are not standardized by this control and are left to the programmer.'),
V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ('V4L2_CID_JPEG_CHROMA_SUBSAMPLING', 'The chroma subsampling factors describe how each component of an input image is sampled, in respect to maximum sample rate in each spatial dimension. See ITU-T.81, clause A.1.1. for more details. The V4L2_CID_JPEG_CHROMA_SUBSAMPLING control determines how Cb and Cr components are downsampled after coverting an input image from RGB to Y’CbCr color space.'),
V4L2_CID_JPEG_RESTART_INTERVAL: ('V4L2_CID_JPEG_RESTART_INTERVAL', 'The restart interval determines an interval of inserting RSTm markers (m = 0..7). The purpose of these markers is to additionally reinitialize the encoder process, in order to process blocks of an image independently. For the lossy compression processes the restart interval unit is MCU (Minimum Coded Unit) and its value is contained in DRI (Define Restart Interval) marker. If V4L2_CID_JPEG_RESTART_INTERVAL control is set to 0, DRI and RSTm markers will not be inserted.'),
V4L2_CID_JPEG_COMPRESSION_QUALITY: ('V4L2_CID_JPEG_COMPRESSION_QUALITY', 'Determines trade-off between image quality and size. It provides simpler method for applications to control image quality, without a need for direct reconfiguration of luminance and chrominance quantization tables. In cases where a driver uses quantization tables configured directly by an application, using interfaces defined elsewhere, V4L2_CID_JPEG_COMPRESSION_QUALITY control should be set by driver to 0. \nThe value range of this control is driver-specific. Only positive, non-zero values are meaningful. The recommended range is 1 - 100, where larger values correspond to better image quality.'),
V4L2_CID_JPEG_ACTIVE_MARKER: ('V4L2_CID_JPEG_ACTIVE_MARKER', 'Specify which JPEG markers are included in compressed stream. This control is valid only for encoders.'),
V4L2_CID_VBLANK: ('V4L2_CID_VBLANK', 'Vertical blanking. The idle period after every frame during which no image data is produced. The unit of vertical blanking is a line. Every line has length of the image width plus horizontal blanking at the pixel rate defined by V4L2_CID_PIXEL_RATE control in the same sub-device.'),
V4L2_CID_HBLANK: ('V4L2_CID_HBLANK', 'Horizontal blanking. The idle period after every line of image data during which no image data is produced. The unit of horizontal blanking is pixels.'),
V4L2_CID_ANALOGUE_GAIN: ('V4L2_CID_ANALOGUE_GAIN', 'Analogue gain is gain affecting all colour components in the pixel matrix. The gain operation is performed in the analogue domain before A/D conversion.'),
V4L2_CID_TEST_PATTERN_RED: ('V4L2_CID_TEST_PATTERN_RED', 'Test pattern red colour component.'),
V4L2_CID_TEST_PATTERN_GREENR: ('V4L2_CID_TEST_PATTERN_GREENR', 'Test pattern green (next to red) colour component.'),
V4L2_CID_TEST_PATTERN_BLUE: ('V4L2_CID_TEST_PATTERN_BLUE', 'Test pattern blue colour component.'),
V4L2_CID_TEST_PATTERN_GREENB: ('V4L2_CID_TEST_PATTERN_GREENB', 'Test pattern green (next to blue) colour component.'),
V4L2_CID_UNIT_CELL_SIZE: ('V4L2_CID_UNIT_CELL_SIZE', 'This control returns the unit cell size in nanometers. The struct v4l2_area provides the width and the height in separate fields to take into consideration asymmetric pixels. This control does not take into consideration any possible hardware binning. The unit cell consists of the whole area of the pixel, sensitive and non-sensitive. This control is required for automatic calibration of sensors/cameras.'),
V4L2_CID_NOTIFY_GAINS: ('V4L2_CID_NOTIFY_GAINS', 'The sensor is notified what gains will be applied to the different colour channels by subsequent processing (such as by an ISP). The sensor is merely informed of these values in case it performs processing that requires them, but it does not apply them itself to the output pixels.\nCurrently it is defined only for Bayer sensors, and is an array control taking 4 gain values, being the gains for each of the Bayer channels. The gains are always in the order B, Gb, Gr and R, irrespective of the exact Bayer order of the sensor itself.\nThe use of an array allows this control to be extended to sensors with, for example, non-Bayer CFAs (colour filter arrays).\nThe units for the gain values are linear, with the default value representing a gain of exactly 1.0. For example, if this default value is reported as being (say) 128, then a value of 192 would represent a gain of exactly 1.5.\n'),
V4L2_CID_LINK_FREQ: ('V4L2_CID_LINK_FREQ', 'The frequency of the data bus (e.g. parallel or CSI-2).'),
V4L2_CID_PIXEL_RATE: ('V4L2_CID_PIXEL_RATE', 'Pixel sampling rate in the device\'s pixel array. This control is read-only and its unit is pixels / second.\nSome devices use horizontal and vertical balanking to configure the frame rate. The frame rate can be calculated from the pixel rate, analogue crop rectangle as well as horizontal and vertical blanking. The pixel rate control may be present in a different sub-device than the blanking controls and the analogue crop rectangle configuration.\nThe configuration of the frame rate is performed by selecting the desired horizontal and vertical blanking. The unit of this control is Hz.'),
V4L2_CID_TEST_PATTERN: ('V4L2_CID_TEST_PATTERN', 'Some capture/display/sensor devices have the capability to generate test pattern images. These hardware specific test patterns can be used to test if a device is working properly.'),
V4L2_CID_DEINTERLACING_MODE: ('V4L2_CID_DEINTERLACING_MODE', 'The video deinterlacing mode (such as Bob, Weave, ...). The menu items are driver specific and are documented in Video4Linux (V4L) driver-specific documentation.'),
V4L2_CID_DIGITAL_GAIN: ('V4L2_CID_DIGITAL_GAIN', 'Digital gain is the value by which all colour components are multiplied by. Typically the digital gain applied is the control value divided by e.g. 0x100, meaning that to get no digital gain the control value needs to be 0x100. The no-gain configuration is also typically the default.'),
}
class v4l2_control(ctypes.Structure):
_fields_ = [
('id', ctypes.c_uint32),
('value', ctypes.c_int32),
]
class v4l2_queryctrl(ctypes.Structure):
_fields_ = [
('id', ctypes.c_uint32),
('type', v4l2_ctrl_type),
('name', ctypes.c_char * 32),
('minimum', ctypes.c_int32),
('maximum', ctypes.c_int32),
('step', ctypes.c_int32),
('default', ctypes.c_int32),
('flags', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 2),
]
class v4l2_querymenu(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('name', ctypes.c_char * 32),
('value', ctypes.c_int64),
]
_fields_ = [
('id', ctypes.c_uint32),
('index', ctypes.c_uint32),
('_u', _u),
('reserved', ctypes.c_uint32),
]
_anonymous_ = ('_u',)
_pack_ = True
class uvc_xu_control_query(ctypes.Structure):
_fields_ = [
('unit', ctypes.c_uint8),
('selector', ctypes.c_uint8),
('query', ctypes.c_uint8), # Video Class-Specific Request Code,
# defined in linux/usb/video.h A.8.
('size', ctypes.c_uint16),
('data', ctypes.c_void_p),
]
V4L2_EVENT_SUB_FL_SEND_INITIAL = 1
V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK = 2
V4L2_EVENT_CTRL = 3
class v4l2_event_subscription(ctypes.Structure):
_fields_ = [
('type', ctypes.c_uint32),
('id', ctypes.c_uint32),
('flags', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 5),
]
class timespec(ctypes.Structure):
_fields_ = [
('tv_sec', ctypes.c_long),
('tv_nsec', ctypes.c_long),
]
V4L2_EVENT_CTRL_CH_VALUE = 1
V4L2_EVENT_CTRL_CH_FLAGS = 2
V4L2_EVENT_CTRL_CH_RANGE = 4
V4L2_EVENT_CTRL_CH_DIMENSIONS = 8
class v4l2_event_ctrl(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('value', ctypes.c_int32),
('value64', ctypes.c_int64),
]
_fields_ = [
('changes', ctypes.c_uint32),
('type', ctypes.c_uint32),
('_u', _u),
('flags', ctypes.c_uint32),
('minimum', ctypes.c_int32),
('maximum', ctypes.c_int32),
('step', ctypes.c_int32),
('default_value', ctypes.c_int32),
]
_anonymous_ = ('_u',)
class v4l2_event(ctypes.Structure):
class _u(ctypes.Union):
_fields_ = [
('ctrl', v4l2_event_ctrl),
('data', ctypes.c_uint8 * 64),
]
_fields_ = [
('type', ctypes.c_uint32),
('_u', _u),
('pending', ctypes.c_uint32),
('sequence', ctypes.c_uint32),
('timestamp', timespec),
('id', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 8),
]
_anonymous_ = ('_u',)
VIDIOC_QUERYCAP = _IOR('V', 0, v4l2_capability)
UVCIOC_CTRL_QUERY = _IOWR('u', 0x21, uvc_xu_control_query)
VIDIOC_G_CTRL = _IOWR('V', 27, v4l2_control)
VIDIOC_S_CTRL = _IOWR('V', 28, v4l2_control)
VIDIOC_QUERYCTRL = _IOWR('V', 36, v4l2_queryctrl)
VIDIOC_QUERYMENU = _IOWR('V', 37, v4l2_querymenu)
VIDIOC_DQEVENT = _IOR('V', 89, v4l2_event)
VIDIOC_SUBSCRIBE_EVENT = _IOW('V', 90, v4l2_event_subscription)
VIDIOC_UNSUBSCRIBE_EVENT = _IOW('V', 91, v4l2_event_subscription)
# A.8. Video Class-Specific Request Codes
UVC_RC_UNDEFINED = 0x00
UVC_SET_CUR = 0x01
UVC_GET_CUR = 0x81
UVC_GET_MIN = 0x82
UVC_GET_MAX = 0x83
UVC_GET_RES = 0x84
UVC_GET_LEN = 0x85
UVC_GET_INFO = 0x86
UVC_GET_DEF = 0x87
EU1_SET_ISP = 0x01
EU1_GET_ISP_RESULT = 0x02
# UVC EU1 extension GUID 23e49ed0-1178-4f31-ae52-d2fb8a8d3b48
UVC_EU1_GUID = b'\xd0\x9e\xe4\x23\x78\x11\x31\x4f\xae\x52\xd2\xfb\x8a\x8d\x3b\x48'
# Razer Kiyo Pro specific registers and values
KIYO_PRO_USB_ID = '1532:0e05'
AF_RESPONSIVE = b'\xff\x06\x00\x00\x00\x00\x00\x00'
AF_PASSIVE = b'\xff\x06\x01\x00\x00\x00\x00\x00'
HDR_OFF = b'\xff\x02\x00\x00\x00\x00\x00\x00'
HDR_ON = b'\xff\x02\x01\x00\x00\x00\x00\x00'
HDR_DARK = b'\xff\x07\x00\x00\x00\x00\x00\x00'
HDR_BRIGHT = b'\xff\x07\x01\x00\x00\x00\x00\x00'
FOV_WIDE = b'\xff\x01\x00\x03\x00\x00\x00\x00'
FOV_MEDIUM_PRE = b'\xff\x01\x00\x03\x01\x00\x00\x00'
FOV_MEDIUM = b'\xff\x01\x01\x03\x01\x00\x00\x00'
FOV_NARROW_PRE = b'\xff\x01\x00\x03\x02\x00\x00\x00'
FOV_NARROW = b'\xff\x01\x01\x03\x02\x00\x00\x00'
# Unknown yet, the synapse sends it in start
UNKNOWN = b'\xff\x04\x00\x00\x00\x00\x00\x00'
# save previous values to the camera
SAVE = b'\xc0\x03\xa8\x00\x00\x00\x00\x00'
LOAD = b'\x00\x00\x00\x00\x00\x00\x00\x00'
def to_buf(b):
return ctypes.create_string_buffer(b)
def try_xu_control(fd, unit_id, selector):
length = ctypes.c_uint16(0)
xu_ctrl_query = uvc_xu_control_query()
xu_ctrl_query.unit = unit_id
xu_ctrl_query.selector = selector
xu_ctrl_query.query = UVC_GET_LEN
xu_ctrl_query.size = 2 # sizeof(length)
xu_ctrl_query.data = ctypes.cast(ctypes.pointer(length), ctypes.c_void_p)
try:
ioctl(fd, UVCIOC_CTRL_QUERY, xu_ctrl_query)
except Exception as e:
logging.debug(f'try_xu_control: UVCIOC_CTRL_QUERY (GET_LEN) - Fd: {fd} - Error: {e}')
return False
return True
def get_length_xu_control(fd, unit_id, selector):
length = ctypes.c_uint16(0)
xu_ctrl_query = uvc_xu_control_query()
xu_ctrl_query.unit = unit_id
xu_ctrl_query.selector = selector
xu_ctrl_query.query = UVC_GET_LEN
xu_ctrl_query.size = 2 # sizeof(length)
xu_ctrl_query.data = ctypes.cast(ctypes.pointer(length), ctypes.c_void_p)
try:
ioctl(fd, UVCIOC_CTRL_QUERY, xu_ctrl_query)
except Exception as e:
logging.warning(f'UVCIOC_CTRL_QUERY (GET_LEN) - Fd: {fd} - Error: {e}')
return length
def query_xu_control(fd, unit_id, selector, query, data):
len = get_length_xu_control(fd, unit_id, selector)
xu_ctrl_query = uvc_xu_control_query()
xu_ctrl_query.unit = unit_id
xu_ctrl_query.selector = selector