35 #include <sys/ioctl.h>
36 #include <sys/types.h>
50 #include <asm/types.h>
52 #include <linux/version.h>
54 #define LINUX_VERSION_CODE 1
55 #define KERNEL_VERSION(...) 1
58 #define ERRMSGSIZ 1024
60 #define CLEAR(x) memset(&(x), 0, sizeof(x))
62 #define XIOCTL(fd, ioctl, arg) xioctl(fd, ioctl, arg, #ioctl)
64 #define DBG_STR_PIX "%c%c%c%c"
65 #define DBG_PIX(pf) ((pf) >> 0) & 0xFF, ((pf) >> 8) & 0xFF, ((pf) >> 16) & 0xFF, ((pf) >> 24) & 0xFF
74 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
75 #define DBG_STR_FLAGS "...%c .%c%c%c %c%c.%c .%c%c%c %c%c%c%c"
76 #define DBG_FLAGS(b) \
77 ((b).flags & V4L2_BUF_FLAG_TSTAMP_SRC_SOE) ? 'S' : 'E', \
78 ((b).flags & V4L2_BUF_FLAG_TIMESTAMP_COPY) ? 'c' : '.', \
79 ((b).flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) ? 'm' : '.', \
80 ((b).flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN) ? 'C' : '.', \
81 ((b).flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE) ? 'I' : '.', \
82 ((b).flags & V4L2_BUF_FLAG_PREPARED) ? 'p' : '.', \
83 ((b).flags & V4L2_BUF_FLAG_TIMECODE) ? 'T' : '.', \
84 ((b).flags & V4L2_BUF_FLAG_ERROR) ? 'E' : '.', \
85 ((b).flags & V4L2_BUF_FLAG_BFRAME) ? 'B' : '.', \
86 ((b).flags & V4L2_BUF_FLAG_PFRAME) ? 'P' : '.', \
87 ((b).flags & V4L2_BUF_FLAG_KEYFRAME) ? 'K' : '.', \
88 ((b).flags & V4L2_BUF_FLAG_DONE) ? 'd' : '.', \
89 ((b).flags & V4L2_BUF_FLAG_QUEUED) ? 'q' : '.', \
90 ((b).flags & V4L2_BUF_FLAG_MAPPED) ? 'm' : '.'
92 #define DBG_STR_FLAGS "%s"
93 #define DBG_FLAGS(b) ""
96 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
97 #define DBG_STR_FMT "%ux%u " DBG_STR_PIX " %scompressed (%ssupported)"
99 (f).fmt.pix.width, (f).fmt.pix.height, DBG_PIX((f).fmt.pix.pixelformat), \
100 ((f).fmt.pix.flags & V4L2_FMT_FLAG_COMPRESSED) ? "" : "un", \
101 (decoder->issupportedformat((f).fmt.pix.pixelformat) ? "" : "un")
103 #define DBG_STR_FMT "%ux%u " DBG_STR_PIX " (%ssupported)"
105 (f).fmt.pix.width, (f).fmt.pix.height, DBG_PIX((f).fmt.pix.pixelformat), \
106 (decoder->issupportedformat((f).fmt.pix.pixelformat) ? "" : "un")
109 #define DBG_STR_BUF "#%d " DBG_STR_FLAGS " % 7d bytes %4.4s seq %d:%d stamp %ld.%06ld"
111 (b).index, DBG_FLAGS(b), (b).bytesused, \
112 ((b).memory == V4L2_MEMORY_MMAP) ? \
114 ((b).memory == V4L2_MEMORY_USERPTR) ? "uptr" : \
115 ((b).memory == 4
) ? \
117 ((b).memory == V4L2_MEMORY_OVERLAY) ? "over" : "", \
118 (b).sequence, (b).field, (b).timestamp.tv_sec, (b).timestamp.tv_usec
135 V4L2_Base::V4L2_Base()
137 frameRate.numerator = 1;
138 frameRate.denominator = 25;
140 selectCallBackID = -1;
156 streamedonce =
false;
159 decoder = v4l2_decode->getDefaultDecoder();
164 has_ext_pix_format =
false;
165 const std::vector<unsigned int> &vsuppformats = decoder->getsupportedformats();
167 "Using default decoder '%s'\n Supported V4L2 formats are:", decoder->getName());
168 for (std::vector<unsigned int>::const_iterator it = vsuppformats.begin(); it != vsuppformats.end(); ++it)
173 getframerate =
nullptr;
174 setframerate =
nullptr;
176 reallocate_buffers =
false;
181 streamactive =
false;
185 V4L2_Base::~V4L2_Base()
201 bool V4L2_Base::is_compressed()
const
204 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
205 switch (fmt.fmt.pix.pixelformat)
207 case V4L2_PIX_FMT_JPEG:
208 case V4L2_PIX_FMT_MJPEG:
210 __FUNCTION__, fmt.fmt.pix.pixelformat, fmt.fmt.pix.pixelformat >> 8,
211 fmt.fmt.pix.pixelformat >> 16, fmt.fmt.pix.pixelformat >> 24);
216 __FUNCTION__, fmt.fmt.pix.pixelformat, fmt.fmt.pix.pixelformat >> 8,
217 fmt.fmt.pix.pixelformat >> 16, fmt.fmt.pix.pixelformat >> 24,
218 fmt.fmt.pix.flags & V4L2_FMT_FLAG_COMPRESSED);
219 return fmt.fmt.pix.flags & V4L2_FMT_FLAG_COMPRESSED;
222 switch (fmt.fmt.pix.pixelformat)
224 case V4L2_PIX_FMT_GREY:
245 int V4L2_Base::xioctl(
int fd,
int request,
void * arg,
char const *
const request_str)
251 r = ioctl(
fd, request, arg);
253 while (-1 == r && EINTR ==
errno);
257 request, request_str,
errno, strerror(
errno));
289 int V4L2_Base::ioctl_set_format(
struct v4l2_format new_fmt,
char * errmsg)
292 if (streamedonce && new_fmt.type)
296 if (open_device(path, errmsg))
307 if (-1 ==
XIOCTL(
fd, VIDIOC_TRY_FMT, &new_fmt))
310 __FUNCTION__,
DBG_FMT(new_fmt));
311 return errno_exit(
"VIDIOC_TRY_FMT", errmsg);
318 if (-1 ==
XIOCTL(
fd, VIDIOC_S_FMT, &new_fmt))
322 return errno_exit(
"VIDIOC_S_FMT", errmsg);
328 new_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
329 if (-1 ==
XIOCTL(
fd, VIDIOC_G_FMT, &new_fmt))
332 return errno_exit(
"VIDIOC_G_FMT", errmsg);
340 decoder->setformat(new_fmt, has_ext_pix_format);
341 this->bpp = decoder->getBpp();
349 int V4L2_Base::errno_exit(
const char * s,
char * errmsg)
351 fprintf(stderr,
"%s error %d, %s\n", s,
errno, strerror(
errno));
355 stop_capturing(errmsg);
360 void V4L2_Base::doDecode(
bool d)
365 int V4L2_Base::connectCam(
const char * devpath,
char * errmsg,
int pixelFormat,
int width,
int height)
370 selectCallBackID = -1;
373 streamedonce =
false;
374 frameRate.numerator = 1;
375 frameRate.denominator = 25;
377 if (open_device(devpath, errmsg) < 0)
382 if (check_device(errmsg) < 0)
389 void V4L2_Base::disconnectCam(
bool stopcapture)
391 if (selectCallBackID != -1)
397 stop_capturing(errmsg);
407 bool V4L2_Base::isLXmodCapable()
409 if (!(strcmp((
const char *)cap.driver,
"pwc")))
469 int V4L2_Base::read_frame(
char * errmsg)
477 cerr <<
"in read Frame method read" << endl;
478 if (-1 == read(
fd, buffers[0].start, buffers[0].length))
488 return errno_exit(
"read", errmsg);
498 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
499 buf.memory = V4L2_MEMORY_MMAP;
504 for (i = 0; i < n_buffers; ++i)
507 if (-1 ==
XIOCTL(
fd, VIDIOC_QUERYBUF, &buf))
512 "%s: invalid buffer query, doing as if buffer was in output queue",
517 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QUERYBUF", errmsg);
524 if (-1 ==
XIOCTL(
fd, VIDIOC_DQBUF, &buf))
529 "%s: no buffer found with DQBUF ioctl (EAGAIN) - frame not ready or not requested",
537 "%s: transitory internal error with DQBUF ioctl (EIO)", __FUNCTION__);
543 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_DQBUF", errmsg);
549 if (buf.flags & V4L2_BUF_FLAG_ERROR)
552 "%s: recoverable error with DQBUF ioctl (BUF_FLAG_ERROR) - frame should be dropped",
554 if (-1 ==
XIOCTL(
fd, VIDIOC_QBUF, &buf))
555 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QBUF", errmsg);
560 if (!is_compressed() && buf.bytesused != fmt.fmt.pix.sizeimage)
563 "%s: frame is %d-byte long, expected %d - frame should be dropped", __FUNCTION__,
564 buf.bytesused, fmt.fmt.pix.sizeimage);
568 unsigned char const * b = (
unsigned char const *)buffers[buf.index].start;
569 unsigned char const * end = b + buf.bytesused;
573 "%s: [%p] %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
574 __FUNCTION__, b, b[0 * 4 + 0], b[0 * 4 + 1], b[0 * 4 + 2], b[0 * 4 + 3],
575 b[1 * 4 + 0], b[1 * 4 + 1], b[1 * 4 + 2], b[1 * 4 + 3], b[2 * 4 + 0], b[2 * 4 + 1],
576 b[2 * 4 + 2], b[2 * 4 + 3], b[3 * 4 + 0], b[3 * 4 + 1], b[3 * 4 + 2],
578 while ((b += 16) < end);
581 if (-1 ==
XIOCTL(
fd, VIDIOC_QBUF, &buf))
582 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QBUF", errmsg);
587 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
589 switch (buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MASK)
591 case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN:
593 case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC:
595 struct timespec uptime = { 0, 0 };
596 clock_gettime(CLOCK_MONOTONIC, &uptime);
598 struct timeval epochtime = { 0, 0 };
602 (epochtime.tv_sec - uptime.tv_sec + buf.timestamp.tv_sec) +
603 (epochtime.tv_usec - uptime.tv_nsec / 1000.0f + buf.timestamp.tv_usec) / 1000000.0f;
605 if (V4L2_BUF_FLAG_TSTAMP_SRC_SOE == (buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK))
608 "%s: frame exposure started %.03f seconds ago", __FUNCTION__, -secs);
610 else if (V4L2_BUF_FLAG_TSTAMP_SRC_EOF == (buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK))
613 "%s: frame finished capturing %.03f seconds ago", __FUNCTION__, -secs);
622 case V4L2_BUF_FLAG_TIMESTAMP_COPY:
630 assert(buf.index < n_buffers);
635 __FUNCTION__, decoder, buf.bytesused, buffers[buf.index].start, cropset ?
'Y' :
'N');
636 decoder->decode((
unsigned char *)(buffers[buf.index].start), &buf, m_Native);
651 if (-1 ==
XIOCTL(
fd, VIDIOC_QBUF, &buf))
652 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QBUF", errmsg);
667 case IO_METHOD_USERPTR:
668 cerr <<
"in read Frame method userptr" << endl;
671 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
672 buf.memory = V4L2_MEMORY_USERPTR;
674 if (-1 ==
XIOCTL(
fd, VIDIOC_DQBUF, &buf))
684 errno_exit(
"VIDIOC_DQBUF", errmsg);
688 for (i = 0; i < n_buffers; ++i)
689 if (buf.m.userptr == (
unsigned long)buffers[i].start && buf.length == buffers[i].length)
692 assert(i < n_buffers);
696 if (-1 ==
XIOCTL(
fd, VIDIOC_QBUF, &buf))
697 errno_exit(
"ReadFrame IO_METHOD_USERPTR: VIDIOC_QBUF", errmsg);
705 int V4L2_Base::stop_capturing(
char * errmsg)
707 enum v4l2_buf_type
type;
720 case IO_METHOD_USERPTR:
724 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
725 if (selectCallBackID != -1)
728 selectCallBackID = -1;
730 streamactive =
false;
732 return errno_exit(
"VIDIOC_STREAMOFF", errmsg);
740 int V4L2_Base::start_capturing(
char * errmsg)
743 enum v4l2_buf_type
type;
755 for (i = 0; i < n_buffers; ++i)
757 struct v4l2_buffer buf;
761 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
762 buf.memory = V4L2_MEMORY_MMAP;
770 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
772 return errno_exit(
"VIDIOC_STREAMON", errmsg);
779 case IO_METHOD_USERPTR:
780 for (i = 0; i < n_buffers; ++i)
782 struct v4l2_buffer buf;
786 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
787 buf.memory = V4L2_MEMORY_USERPTR;
788 buf.m.userptr = (
unsigned long)buffers[i].start;
789 buf.length = buffers[i].length;
791 if (-1 ==
XIOCTL(
fd, VIDIOC_QBUF, &buf))
792 return errno_exit(
"StartCapturing IO_METHOD_USERPTR: VIDIOC_QBUF", errmsg);
795 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
798 return errno_exit(
"VIDIOC_STREAMON", errmsg);
808 void V4L2_Base::newFrame(
int ,
void * p)
815 int V4L2_Base::uninit_device(
char * errmsg)
820 free(buffers[0].start);
824 for (
unsigned int i = 0; i < n_buffers; ++i)
825 if (-1 == munmap(buffers[i].start, buffers[i].length))
826 return errno_exit(
"munmap", errmsg);
829 case IO_METHOD_USERPTR:
830 for (
unsigned int i = 0; i < n_buffers; ++i)
831 free(buffers[i].start);
840 void V4L2_Base::init_read(
unsigned int buffer_size)
842 buffers = (
buffer *)calloc(1,
sizeof(*buffers));
846 fprintf(stderr,
"Out of memory\n");
850 buffers[0].length = buffer_size;
851 buffers[0].start = malloc(buffer_size);
853 if (!buffers[0].start)
855 fprintf(stderr,
"Out of memory\n");
860 int V4L2_Base::init_mmap(
char * errmsg)
862 struct v4l2_requestbuffers req;
868 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
869 req.memory = V4L2_MEMORY_MMAP;
871 if (-1 ==
XIOCTL(
fd, VIDIOC_REQBUFS, &req))
875 fprintf(stderr,
"%.*s does not support memory mapping\n", (
int)
sizeof(dev_name), dev_name);
876 snprintf(errmsg,
ERRMSGSIZ,
"%.*s does not support memory mapping\n", (
int)
sizeof(dev_name), dev_name);
881 return errno_exit(
"VIDIOC_REQBUFS", errmsg);
887 fprintf(stderr,
"Insufficient buffer memory on %.*s\n", (
int)
sizeof(dev_name), dev_name);
888 snprintf(errmsg,
ERRMSGSIZ,
"Insufficient buffer memory on %.*s\n", (
int)
sizeof(dev_name), dev_name);
892 buffers = (
buffer *)calloc(req.count,
sizeof(*buffers));
896 fprintf(stderr,
"buffers. Out of memory\n");
897 strncpy(errmsg,
"buffers. Out of memory\n",
ERRMSGSIZ);
901 for (n_buffers = 0; n_buffers < req.count; n_buffers++)
903 struct v4l2_buffer buf;
907 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
908 buf.memory = V4L2_MEMORY_MMAP;
909 buf.index = n_buffers;
911 if (-1 ==
XIOCTL(
fd, VIDIOC_QUERYBUF, &buf))
912 return errno_exit(
"VIDIOC_QUERYBUF", errmsg);
914 buffers[n_buffers].length = buf.length;
915 buffers[n_buffers].start = mmap(
nullptr , buf.length, PROT_READ | PROT_WRITE ,
916 MAP_SHARED ,
fd, buf.m.offset);
918 if (MAP_FAILED == buffers[n_buffers].start)
919 return errno_exit(
"mmap", errmsg);
925 void V4L2_Base::init_userp(
unsigned int buffer_size)
927 struct v4l2_requestbuffers req;
933 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
934 req.memory = V4L2_MEMORY_USERPTR;
936 if (-1 ==
XIOCTL(
fd, VIDIOC_REQBUFS, &req))
940 fprintf(stderr,
"%.*s does not support user pointer i/o\n", (
int)
sizeof(dev_name), dev_name);
945 errno_exit(
"VIDIOC_REQBUFS", errmsg);
949 buffers = (
buffer *)calloc(4,
sizeof(*buffers));
953 fprintf(stderr,
"Out of memory\n");
957 for (n_buffers = 0; n_buffers < 4; ++n_buffers)
959 buffers[n_buffers].length = buffer_size;
960 buffers[n_buffers].start = malloc(buffer_size);
962 if (!buffers[n_buffers].start)
964 fprintf(stderr,
"Out of memory\n");
970 int V4L2_Base::check_device(
char * errmsg)
972 struct v4l2_input input_avail;
974 if (-1 ==
XIOCTL(
fd, VIDIOC_QUERYCAP, &cap))
978 fprintf(stderr,
"%.*s is no V4L2 device\n", (
int)
sizeof(dev_name), dev_name);
979 snprintf(errmsg,
ERRMSGSIZ,
"%.*s is no V4L2 device\n", (
int)
sizeof(dev_name), dev_name);
984 return errno_exit(
"VIDIOC_QUERYCAP", errmsg);
989 cap.driver, (cap.version >> 16) & 0xFF, (cap.version >> 8) & 0xFF, (cap.version & 0xFF));
993 setframerate = &V4L2_Base::stdsetframerate;
994 getframerate = &V4L2_Base::stdgetframerate;
1011 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
1013 if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
1015 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
1017 if (cap.capabilities & V4L2_CAP_VBI_CAPTURE)
1019 if (cap.capabilities & V4L2_CAP_VBI_OUTPUT)
1021 if (cap.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE)
1023 if (cap.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
1025 if (cap.capabilities & V4L2_CAP_RDS_CAPTURE)
1027 if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
1029 if (cap.capabilities & V4L2_CAP_TUNER)
1031 if (cap.capabilities & V4L2_CAP_AUDIO)
1033 if (cap.capabilities & V4L2_CAP_RADIO)
1035 if (cap.capabilities & V4L2_CAP_READWRITE)
1037 if (cap.capabilities & V4L2_CAP_ASYNCIO)
1039 if (cap.capabilities & V4L2_CAP_STREAMING)
1045 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
1047 fprintf(stderr,
"%.*s is no video capture device\n", (
int)
sizeof(dev_name), dev_name);
1048 snprintf(errmsg,
ERRMSGSIZ,
"%.*s is no video capture device", (
int)
sizeof(dev_name), dev_name);
1054 case IO_METHOD_READ:
1055 if (!(cap.capabilities & V4L2_CAP_READWRITE))
1057 fprintf(stderr,
"%.*s does not support read i/o", (
int)
sizeof(dev_name), dev_name);
1058 snprintf(errmsg,
ERRMSGSIZ,
"%.*s does not support read i/o", (
int)
sizeof(dev_name), dev_name);
1063 case IO_METHOD_MMAP:
1064 case IO_METHOD_USERPTR:
1065 if (!(cap.capabilities & V4L2_CAP_STREAMING))
1067 fprintf(stderr,
"%.*s does not support streaming i/o", (
int)
sizeof(dev_name), dev_name);
1068 snprintf(errmsg,
ERRMSGSIZ,
"%.*s does not support streaming i/o", (
int)
sizeof(dev_name), dev_name);
1077 if (-1 == ioctl(
fd, VIDIOC_G_INPUT, &input.index))
1079 perror(
"VIDIOC_G_INPUT");
1084 for (input_avail.index = 0; ioctl(
fd, VIDIOC_ENUMINPUT, &input_avail) != -1; input_avail.index++)
1086 (
int)
sizeof(input_avail.name), input_avail.name,
1087 (input_avail.type == V4L2_INPUT_TYPE_TUNER ?
"Tuner/RF Demodulator" :
"Composite/S-Video"),
1088 input.index == input_avail.index ?
" current" :
"");
1089 if (
errno != EINVAL)
1091 enumeratedInputs = input_avail.index;
1094 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1096 if (-1 ==
XIOCTL(
fd, VIDIOC_CROPCAP, &cropcap))
1098 perror(
"VIDIOC_CROPCAP");
1106 " Crop capabilities: bounds = (top=%d, left=%d, width=%d, height=%d)", cropcap.bounds.top,
1107 cropcap.bounds.left, cropcap.bounds.width, cropcap.bounds.height);
1109 " Crop capabilities: defrect = (top=%d, left=%d, width=%d, height=%d)", cropcap.defrect.top,
1110 cropcap.defrect.left, cropcap.defrect.width, cropcap.defrect.height);
1112 cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
1114 crop.c.top = cropcap.defrect.top;
1115 crop.c.left = cropcap.defrect.left;
1116 crop.c.width = cropcap.defrect.width;
1117 crop.c.height = cropcap.defrect.height;
1118 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CROP, &crop))
1120 perror(
"VIDIOC_S_CROP");
1124 if (-1 ==
XIOCTL(
fd, VIDIOC_G_CROP, &crop))
1126 perror(
"VIDIOC_G_CROP");
1132 decoder->usesoftcrop(!cancrop);
1136 struct v4l2_fmtdesc fmt_avail;
1137 fmt_avail.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1140 for (fmt_avail.index = 0; ioctl(
fd, VIDIOC_ENUM_FMT, &fmt_avail) != -1; fmt_avail.index++)
1145 (
int)
sizeof(fmt_avail.description), fmt_avail.description, (fmt_avail.pixelformat) & 0xFF,
1146 (fmt_avail.pixelformat >> 8) & 0xFF, (fmt_avail.pixelformat >> 16) & 0xFF,
1147 (fmt_avail.pixelformat >> 24) & 0xFF,
1148 (decoder->issupportedformat(fmt_avail.pixelformat) ?
"supported" :
"UNSUPPORTED"));
1151 struct v4l2_frmsizeenum frm_sizeenum;
1152 frm_sizeenum.pixel_format = fmt_avail.pixelformat;
1154 " Enumerating available Frame sizes/rates for this format:");
1155 for (frm_sizeenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMESIZES, &frm_sizeenum) != -1;
1156 frm_sizeenum.index++)
1158 switch (frm_sizeenum.type)
1160 case V4L2_FRMSIZE_TYPE_DISCRETE:
1162 " %2d. (Discrete) width %d x height %d\n", frm_sizeenum.index,
1163 frm_sizeenum.discrete.width, frm_sizeenum.discrete.height);
1165 case V4L2_FRMSIZE_TYPE_STEPWISE:
1167 " (Stepwise) min. width %d, max. width %d step width %d",
1168 frm_sizeenum.stepwise.min_width, frm_sizeenum.stepwise.max_width,
1169 frm_sizeenum.stepwise.step_width);
1171 " (Stepwise) min. height %d, max. height %d step height %d ",
1172 frm_sizeenum.stepwise.min_height, frm_sizeenum.stepwise.max_height,
1173 frm_sizeenum.stepwise.step_height);
1175 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1177 " (Continuous--step=1) min. width %d, max. width %d",
1178 frm_sizeenum.stepwise.min_width, frm_sizeenum.stepwise.max_width);
1180 " (Continuous--step=1) min. height %d, max. height %d ",
1181 frm_sizeenum.stepwise.min_height, frm_sizeenum.stepwise.max_height);
1190 struct v4l2_frmivalenum frmi_valenum;
1191 frmi_valenum.pixel_format = fmt_avail.pixelformat;
1192 if (frm_sizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE)
1194 frmi_valenum.width = frm_sizeenum.discrete.width;
1195 frmi_valenum.height = frm_sizeenum.discrete.height;
1199 frmi_valenum.width = frm_sizeenum.stepwise.max_width;
1200 frmi_valenum.height = frm_sizeenum.stepwise.max_height;
1202 frmi_valenum.type = 0;
1203 frmi_valenum.stepwise.min.numerator = 0;
1204 frmi_valenum.stepwise.min.denominator = 0;
1205 frmi_valenum.stepwise.max.numerator = 0;
1206 frmi_valenum.stepwise.max.denominator = 0;
1207 frmi_valenum.stepwise.step.numerator = 0;
1208 frmi_valenum.stepwise.step.denominator = 0;
1210 for (frmi_valenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmi_valenum) != -1;
1211 frmi_valenum.index++)
1213 switch (frmi_valenum.type)
1215 case V4L2_FRMIVAL_TYPE_DISCRETE:
1217 frmi_valenum.discrete.numerator, frmi_valenum.discrete.denominator);
1219 case V4L2_FRMIVAL_TYPE_STEPWISE:
1222 " (Stepwise) min. %d/%ds, max. %d / %d s, step %d / %d s",
1223 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1224 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator,
1225 frmi_valenum.stepwise.step.numerator, frmi_valenum.stepwise.step.denominator);
1227 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1230 " (Continuous) min. %d / %d s, max. %d / %d s",
1231 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1232 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator);
1236 " Unknown Frame rate type: %d", frmi_valenum.type);
1240 if (frmi_valenum.index == 0)
1242 perror(
"VIDIOC_ENUM_FRAMEINTERVALS");
1243 switch (frmi_valenum.type)
1245 case V4L2_FRMIVAL_TYPE_DISCRETE:
1247 frmi_valenum.discrete.numerator, frmi_valenum.discrete.denominator);
1249 case V4L2_FRMIVAL_TYPE_STEPWISE:
1252 " (Stepwise) min. %d/%ds, max. %d / %d s, step %d / %d s",
1253 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1254 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator,
1255 frmi_valenum.stepwise.step.numerator, frmi_valenum.stepwise.step.denominator);
1257 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1260 " (Continuous) min. %d / %d s, max. %d / %d s",
1261 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1262 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator);
1266 " Unknown Frame rate type: %d", frmi_valenum.type);
1275 if (
errno != EINVAL)
1277 enumeratedCaptureFormats = fmt_avail.index;
1307 return ioctl_set_format(fmt, errmsg);
1310 int V4L2_Base::init_device(
char * errmsg)
1320 case IO_METHOD_READ:
1321 init_read(fmt.fmt.pix.sizeimage);
1324 case IO_METHOD_MMAP:
1325 return init_mmap(errmsg);
1328 case IO_METHOD_USERPTR:
1329 init_userp(fmt.fmt.pix.sizeimage);
1335 void V4L2_Base::close_device()
1338 uninit_device(errmsg);
1340 if (-1 == close(
fd))
1341 errno_exit(
"close", errmsg);
1346 int V4L2_Base::open_device(
const char * devpath,
char * errmsg)
1350 strncpy(dev_name, devpath, 64);
1352 if (-1 == stat(dev_name, &st))
1354 fprintf(stderr,
"Cannot identify %.*s: %d, %s\n", (
int)
sizeof(dev_name), dev_name,
errno, strerror(
errno));
1355 snprintf(errmsg,
ERRMSGSIZ,
"Cannot identify %.*s: %d, %s\n", (
int)
sizeof(dev_name), dev_name,
errno,
1360 if (!S_ISCHR(st.st_mode))
1362 fprintf(stderr,
"%.*s is no device\n", (
int)
sizeof(dev_name), dev_name);
1363 snprintf(errmsg,
ERRMSGSIZ,
"%.*s is no device\n", (
int)
sizeof(dev_name), dev_name);
1367 fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
1371 fprintf(stderr,
"Cannot open %.*s: %d, %s\n", (
int)
sizeof(dev_name), dev_name,
errno, strerror(
errno));
1372 snprintf(errmsg,
ERRMSGSIZ,
"Cannot open %.*s: %d, %s\n", (
int)
sizeof(dev_name), dev_name,
errno,
1377 streamedonce =
false;
1378 snprintf(errmsg,
ERRMSGSIZ,
"%s\n", strerror(0));
1391 struct v4l2_input input_avail;
1394 size_t const inputsLen = enumeratedInputs *
sizeof(
ISwitch);
1398 memset(inputs, 0, inputsLen);
1401 for (input_avail.index = 0; (
int)input_avail.index < enumeratedInputs; input_avail.index++)
1404 if (
XIOCTL(
fd, VIDIOC_ENUMINPUT, &input_avail))
1408 strncpy(inputs[input_avail.index].name, (
const char *)input_avail.name,
MAXINDINAME);
1409 strncpy(inputs[input_avail.index].label, (
const char *)input_avail.name,
MAXINDILABEL);
1417 inputssp->
sp = inputs;
1418 inputssp->
nsp = input_avail.index;
1423 inputs[input.index].s =
ISS_ON;
1425 (
int)
sizeof(inputs[input.index].name), inputs[input.index].name);
1428 int V4L2_Base::setinput(
unsigned int inputindex,
char * errmsg)
1435 if (open_device(path, errmsg))
1442 if (-1 ==
XIOCTL(
fd, VIDIOC_S_INPUT, &inputindex))
1444 return errno_exit(
"VIDIOC_S_INPUT", errmsg);
1446 if (-1 ==
XIOCTL(
fd, VIDIOC_G_INPUT, &input.index))
1448 return errno_exit(
"VIDIOC_G_INPUT", errmsg);
1460 if (!captureformatssp)
1463 struct v4l2_fmtdesc fmt_avail;
1466 size_t const formatsLen = enumeratedCaptureFormats *
sizeof(
ISwitch);
1470 memset(formats, 0, formatsLen);
1473 fmt_avail.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1474 for (fmt_avail.index = 0; (
int)fmt_avail.index < enumeratedCaptureFormats; fmt_avail.index++)
1477 if (
XIOCTL(
fd, VIDIOC_ENUM_FMT, &fmt_avail))
1481 strncpy(formats[fmt_avail.index].name, (
const char *)fmt_avail.description,
MAXINDINAME);
1482 strncpy(formats[fmt_avail.index].label, (
const char *)fmt_avail.description,
MAXINDILABEL);
1486 formats[fmt_avail.index].aux = (
int *)malloc(
sizeof(
int));
1487 if (!formats[fmt_avail.index].aux)
1489 *(
int *)formats[fmt_avail.index].aux = fmt_avail.pixelformat;
1493 if (captureformatssp->
sp)
1494 free(captureformatssp->
sp);
1497 captureformatssp->
sp = formats;
1498 captureformatssp->
nsp = fmt_avail.index;
1502 for (
unsigned int i = 0; i < fmt_avail.index; i++)
1504 if ((
int)fmt.fmt.pix.pixelformat == *(
int *)formats[i].aux)
1508 (fmt.fmt.pix.pixelformat) & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF,
1509 (fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF);
1522 int V4L2_Base::setcaptureformat(
unsigned int captureformat,
char * errmsg)
1524 struct v4l2_format new_fmt;
1527 new_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1528 new_fmt.fmt.pix.pixelformat = captureformat;
1530 return ioctl_set_format(new_fmt, errmsg);
1535 struct v4l2_frmsizeenum frm_sizeenum;
1537 INumber * sizevalue =
nullptr;
1538 bool sizefound =
false;
1543 if (capturesizessp->
sp)
1544 free(capturesizessp->
sp);
1545 if (capturesizenp->
np)
1546 free(capturesizenp->
np);
1548 frm_sizeenum.pixel_format = fmt.fmt.pix.pixelformat;
1550 for (frm_sizeenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMESIZES, &frm_sizeenum) != -1; frm_sizeenum.index++)
1552 switch (frm_sizeenum.type)
1554 case V4L2_FRMSIZE_TYPE_DISCRETE:
1555 sizes = (sizes ==
nullptr) ? (
ISwitch *)malloc(
sizeof(
ISwitch)) :
1556 (
ISwitch *)realloc(sizes, (frm_sizeenum.index + 1) *
sizeof(
ISwitch));
1558 snprintf(sizes[frm_sizeenum.index].name,
MAXINDINAME,
"%dx%d", frm_sizeenum.discrete.width,
1559 frm_sizeenum.discrete.height);
1560 snprintf(sizes[frm_sizeenum.index].label,
MAXINDINAME,
"%dx%d", frm_sizeenum.discrete.width,
1561 frm_sizeenum.discrete.height);
1562 sizes[frm_sizeenum.index].s =
ISS_OFF;
1565 if ((fmt.fmt.pix.width == frm_sizeenum.discrete.width) &&
1566 (fmt.fmt.pix.height == frm_sizeenum.discrete.height))
1568 sizes[frm_sizeenum.index].s =
ISS_ON;
1571 frm_sizeenum.index, frm_sizeenum.discrete.width, frm_sizeenum.discrete.height);
1575 case V4L2_FRMSIZE_TYPE_STEPWISE:
1576 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1578 IUFillNumber(sizevalue,
"Width",
"Width",
"%.0f", frm_sizeenum.stepwise.min_width,
1579 frm_sizeenum.stepwise.max_width, frm_sizeenum.stepwise.step_width, fmt.fmt.pix.width);
1580 IUFillNumber(sizevalue + 1,
"Height",
"Height",
"%.0f", frm_sizeenum.stepwise.min_height,
1581 frm_sizeenum.stepwise.max_height, frm_sizeenum.stepwise.step_height, fmt.fmt.pix.height);
1583 fmt.fmt.pix.height);
1591 if (sizes !=
nullptr)
1593 capturesizessp->
sp = sizes;
1594 capturesizessp->
nsp = frm_sizeenum.index;
1595 capturesizenp->
np =
nullptr;
1599 capturesizenp->
np = sizevalue;
1600 capturesizenp->
nnp = 2;
1601 capturesizessp->
sp =
nullptr;
1612 int V4L2_Base::setcapturesize(
unsigned int w,
unsigned int h,
char * errmsg)
1614 struct v4l2_format new_fmt = fmt;
1616 new_fmt.fmt.pix.width = w;
1617 new_fmt.fmt.pix.height = h;
1619 return ioctl_set_format(new_fmt, errmsg);
1624 struct v4l2_frmivalenum frmi_valenum;
1626 INumber * ratevalue =
nullptr;
1627 struct v4l2_fract frate;
1629 if (frameratessp->
sp)
1630 free(frameratessp->
sp);
1631 if (frameratenp->
np)
1632 free(frameratenp->
np);
1633 frate = (this->*getframerate)();
1635 bzero(&frmi_valenum,
sizeof(frmi_valenum));
1636 frmi_valenum.pixel_format = fmt.fmt.pix.pixelformat;
1637 frmi_valenum.width = fmt.fmt.pix.width;
1638 frmi_valenum.height = fmt.fmt.pix.height;
1640 for (frmi_valenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmi_valenum) != -1; frmi_valenum.index++)
1642 switch (frmi_valenum.type)
1644 case V4L2_FRMIVAL_TYPE_DISCRETE:
1645 rates = (rates ==
nullptr) ? (
ISwitch *)malloc(
sizeof(
ISwitch)) :
1646 (
ISwitch *)realloc(rates, (frmi_valenum.index + 1) *
sizeof(
ISwitch));
1647 snprintf(rates[frmi_valenum.index].name,
MAXINDINAME,
"%d/%d", frmi_valenum.discrete.numerator,
1648 frmi_valenum.discrete.denominator);
1649 snprintf(rates[frmi_valenum.index].label,
MAXINDINAME,
"%d/%d", frmi_valenum.discrete.numerator,
1650 frmi_valenum.discrete.denominator);
1651 if ((frate.numerator == frmi_valenum.discrete.numerator) &&
1652 (frate.denominator == frmi_valenum.discrete.denominator))
1655 frmi_valenum.discrete.numerator, frmi_valenum.discrete.denominator);
1656 rates[frmi_valenum.index].s =
ISS_ON;
1659 rates[frmi_valenum.index].s =
ISS_OFF;
1661 case V4L2_FRMIVAL_TYPE_STEPWISE:
1662 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1664 IUFillNumber(ratevalue,
"V4L2_FRAME_INTERVAL",
"Frame Interval",
"%.0f",
1665 frmi_valenum.stepwise.min.numerator / (
double)frmi_valenum.stepwise.min.denominator,
1666 frmi_valenum.stepwise.max.numerator / (
double)frmi_valenum.stepwise.max.denominator,
1667 frmi_valenum.stepwise.step.numerator / (
double)frmi_valenum.stepwise.step.denominator,
1668 frate.numerator / (
double)frate.denominator);
1675 frameratessp->
sp =
nullptr;
1676 frameratessp->
nsp = 0;
1677 frameratenp->
np =
nullptr;
1678 frameratenp->
nnp = 0;
1679 if (frmi_valenum.index != 0)
1681 if (rates !=
nullptr)
1683 frameratessp->
sp = rates;
1684 frameratessp->
nsp = frmi_valenum.index;
1688 frameratenp->
np = ratevalue;
1689 frameratenp->
nnp = 1;
1694 int V4L2_Base::setcroprect(
int x,
int y,
int w,
int h,
char * errmsg)
1697 if (x == 0 && y == 0 && w == (
int)fmt.fmt.pix.width && h == (
int)fmt.fmt.pix.height)
1700 decoder->resetcrop();
1704 int const pix_width =
static_cast <int> (fmt.fmt.pix.width);
1705 int const pix_height =
static_cast <int> (fmt.fmt.pix.height);
1708 crop.c.left = 0 <= x ? x < pix_width ? x : pix_width - 1 : 0;
1709 crop.c.top = 0 <= y ? y < pix_height ? y : pix_height - 1 : 0;
1710 crop.c.width = 0 <= w ? w < pix_width ? w : pix_width : 0;
1711 crop.c.height = 0 <= h ? h < pix_height ? h : pix_height : 0;
1714 if (x + w < 0 || y + h < 0 || pix_width <= x || pix_height <= y)
1716 strncpy(errmsg,
"requested crop rectangle is outside of frame",
ERRMSGSIZ);
1733 if (0 + pix_width < x + w)
1737 if (0 + pix_height < y + h)
1743 struct v4l2_crop software_crop;
1744 software_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1745 software_crop.c.left = x;
1746 software_crop.c.top = y;
1747 software_crop.c.width = w;
1748 software_crop.c.height = h;
1754 struct v4l2_crop hardware_crop = software_crop;
1759 hardware_crop.c.top--;
1760 hardware_crop.c.height++;
1766 hardware_crop.c.height++;
1770 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CROP, &hardware_crop))
1773 "Failed V4L2 hardware crop request 0x%08X (%dx%d at (%d, %d)), falling back to software crop",
1774 (
unsigned int)VIDIOC_S_CROP, hardware_crop.c.width, hardware_crop.c.height,
1775 hardware_crop.c.left, hardware_crop.c.top);
1778 else if (-1 ==
XIOCTL(
fd, VIDIOC_G_CROP, &hardware_crop))
1785 (
unsigned int)VIDIOC_S_CROP, hardware_crop.c.width, hardware_crop.c.height,
1786 hardware_crop.c.left, hardware_crop.c.top);
1791 bool const softcrop = decoder->setcrop(software_crop);
1793 if (!softcrop && !cancrop)
1796 strncpy(errmsg,
"No hardware and software cropping for this format",
ERRMSGSIZ);
1802 crop = software_crop;
1805 crop.c.height, crop.c.left, crop.c.top);
1809 int V4L2_Base::getWidth()
1812 return crop.c.width;
1814 return fmt.fmt.pix.width;
1817 int V4L2_Base::getHeight()
1820 return crop.c.height;
1822 return fmt.fmt.pix.height;
1825 int V4L2_Base::getBpp()
1830 int V4L2_Base::getFormat()
1832 return fmt.fmt.pix.pixelformat;
1835 struct v4l2_rect
V4L2_Base::getcroprect()
1840 int V4L2_Base::stdsetframerate(
struct v4l2_fract frate,
char * errmsg)
1842 struct v4l2_streamparm sparm;
1844 bzero(&sparm,
sizeof(
struct v4l2_streamparm));
1845 sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1846 sparm.parm.capture.timeperframe = frate;
1847 if (-1 ==
XIOCTL(
fd, VIDIOC_S_PARM, &sparm))
1850 return errno_exit(
"VIDIOC_S_PARM", errmsg);
1861 int V4L2_Base::pwcsetframerate(
struct v4l2_fract frate,
char * errmsg)
1863 int const fps = frate.denominator / frate.numerator;
1865 struct v4l2_format new_fmt = fmt;
1868 if (-1 == ioctl_set_format(new_fmt, errmsg))
1869 return errno_exit(
"pwcsetframerate", errmsg);
1876 struct v4l2_fract
V4L2_Base::stdgetframerate()
1878 struct v4l2_streamparm sparm;
1880 bzero(&sparm,
sizeof(
struct v4l2_streamparm));
1881 sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1882 if (-1 ==
XIOCTL(
fd, VIDIOC_G_PARM, &sparm))
1884 perror(
"VIDIOC_G_PARM");
1888 frameRate = sparm.parm.capture.timeperframe;
1897 return ((
char *)cap.card);
1900 void V4L2_Base::getMaxMinSize(
int &x_max,
int &y_max,
int &x_min,
int &y_min)
1914 int V4L2_Base::setSize(
int x,
int y)
1917 struct v4l2_format new_fmt = fmt;
1919 new_fmt.fmt.pix.width = x;
1920 new_fmt.fmt.pix.height = y;
1922 if (-1 == ioctl_set_format(new_fmt, errmsg))
1935 void V4L2_Base::setColorProcessing(
bool quantization,
bool colorconvert,
bool linearization)
1938 decoder->setQuantization(quantization);
1939 decoder->setLinearization(linearization);
1940 bpp = decoder->getBpp();
1943 unsigned char * V4L2_Base::getY()
1945 return decoder->getY();
1948 unsigned char * V4L2_Base::getU()
1950 return decoder->getU();
1953 unsigned char * V4L2_Base::getV()
1955 return decoder->getV();
1958 unsigned char * V4L2_Base::getMJPEGBuffer(
int &size)
1960 return decoder->getMJPEGBuffer(size);
1963 unsigned char * V4L2_Base::getRGBBuffer()
1965 return decoder->getRGBBuffer();
1968 float * V4L2_Base::getLinearY()
1970 return decoder->getLinearY();
1973 void V4L2_Base::registerCallback(
WPF * fp,
void * ud)
1979 void V4L2_Base::findMinMax()
1982 struct v4l2_format tryfmt;
1985 xmin = xmax = fmt.fmt.pix.width;
1986 ymin = ymax = fmt.fmt.pix.height;
1988 tryfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1989 tryfmt.fmt.pix.width = 10;
1990 tryfmt.fmt.pix.height = 10;
1991 tryfmt.fmt.pix.pixelformat = fmt.fmt.pix.pixelformat;
1992 tryfmt.fmt.pix.field = fmt.fmt.pix.field;
1994 if (-1 ==
XIOCTL(
fd, VIDIOC_TRY_FMT, &tryfmt))
1996 errno_exit(
"VIDIOC_TRY_FMT 1", errmsg);
2000 xmin = tryfmt.fmt.pix.width;
2001 ymin = tryfmt.fmt.pix.height;
2003 tryfmt.fmt.pix.width = 1600;
2004 tryfmt.fmt.pix.height = 1200;
2006 if (-1 ==
XIOCTL(
fd, VIDIOC_TRY_FMT, &tryfmt))
2008 errno_exit(
"VIDIOC_TRY_FMT 2", errmsg);
2012 xmax = tryfmt.fmt.pix.width;
2013 ymax = tryfmt.fmt.pix.height;
2015 cerr <<
"Min X: " << xmin <<
" - Max X: " << xmax <<
" - Min Y: " << ymin <<
" - Max Y: " << ymax << endl;
2018 void V4L2_Base::enumerate_ctrl()
2023 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
2025 if (0 ==
XIOCTL(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2027 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2029 cerr <<
"DISABLED--Control " << queryctrl.name << endl;
2032 cerr <<
"Control " << queryctrl.name << endl;
2033 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2034 if ((queryctrl.type == V4L2_CTRL_TYPE_MENU) || (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2036 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2039 if (queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2040 cerr <<
" boolean" << endl;
2041 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2042 cerr <<
" integer" << endl;
2045 if (queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2046 cerr <<
" button" << endl;
2050 if (
errno == EINVAL)
2053 errno_exit(
"VIDIOC_QUERYCTRL", errmsg);
2058 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;; queryctrl.id++)
2060 if (0 ==
XIOCTL(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2062 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2064 cerr <<
"DISABLED--Private Control " << queryctrl.name << endl;
2068 cerr <<
"Private Control " << queryctrl.name << endl;
2069 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2070 if ((queryctrl.type == V4L2_CTRL_TYPE_MENU) || (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2072 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2075 if (queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2076 cerr <<
" boolean" << endl;
2077 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2078 cerr <<
" integer" << endl;
2081 if (queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2082 cerr <<
" button" << endl;
2086 if (
errno == EINVAL)
2089 errno_exit(
"VIDIOC_QUERYCTRL", errmsg);
2095 void V4L2_Base::enumerate_menu()
2097 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2098 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2099 cerr <<
" Menu items:" << endl;
2100 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2101 cerr <<
" Integer Menu items:" << endl;
2103 cerr <<
" Menu items:" << endl;
2107 querymenu.id = queryctrl.id;
2109 for (querymenu.index = queryctrl.minimum; (
int)querymenu.index <= queryctrl.maximum; querymenu.index++)
2111 if (0 ==
XIOCTL(
fd, VIDIOC_QUERYMENU, &querymenu))
2113 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2114 cerr <<
" " << querymenu.name << endl;
2115 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2116 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2119 menuname[18] =
'\0';
2120 snprintf(menuname, 19,
"0x%016llX", querymenu.value);
2121 cerr <<
" " << menuname << endl;
2133 int V4L2_Base::query_ctrl(
unsigned int ctrl_id,
double &ctrl_min,
double &ctrl_max,
double &ctrl_step,
2134 double &ctrl_value,
char * errmsg)
2136 struct v4l2_control control;
2140 queryctrl.id = ctrl_id;
2142 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2144 if (
errno != EINVAL)
2145 return errno_exit(
"VIDIOC_QUERYCTRL", errmsg);
2149 cerr <<
"#" << ctrl_id <<
" is not supported" << endl;
2150 snprintf(errmsg,
ERRMSGSIZ,
"# %d is not supported", ctrl_id);
2154 else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2156 cerr <<
"#" << ctrl_id <<
" is disabled" << endl;
2157 snprintf(errmsg,
ERRMSGSIZ,
"# %d is disabled", ctrl_id);
2161 ctrl_min = queryctrl.minimum;
2162 ctrl_max = queryctrl.maximum;
2163 ctrl_step = queryctrl.step;
2164 ctrl_value = queryctrl.default_value;
2168 control.id = ctrl_id;
2170 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2171 ctrl_value = control.value;
2173 cerr << queryctrl.name <<
" -- min: " << ctrl_min <<
" max: " << ctrl_max <<
" step: " << ctrl_step
2174 <<
" value: " << ctrl_value << endl;
2180 unsigned int * noptions,
const char * dev,
const char * group)
2182 struct v4l2_control control;
2185 unsigned int * num_ctrls =
nullptr;
2188 unsigned int nopt = 0;
2189 char optname[] =
"OPT000";
2190 char swonname[] =
"SET_OPT000";
2191 char swoffname[] =
"UNSET_OPT000";
2192 char menuname[] =
"MENU000";
2193 char menuoptname[] =
"MENU000_OPT000";
2199 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
2201 if (0 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2203 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2205 cerr << queryctrl.name <<
" is disabled." << endl;
2209 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2211 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2214 num_ctrls = (num_ctrls ==
nullptr) ?
2215 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2216 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2221 numbers[nnum].min = queryctrl.minimum;
2222 numbers[nnum].max = queryctrl.maximum;
2223 numbers[nnum].step = queryctrl.step;
2224 numbers[nnum].value = queryctrl.default_value;
2228 control.id = queryctrl.id;
2229 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2230 numbers[nnum].value = control.value;
2233 num_ctrls[nnum] = queryctrl.id;
2235 cerr <<
"Adding " << queryctrl.name <<
" -- min: " << queryctrl.minimum <<
" max: " << queryctrl.maximum
2236 <<
" step: " << queryctrl.step <<
" value: " << numbers[nnum].value << endl;
2240 if (queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2243 snprintf(optname + 3, 4,
"%03d", nopt);
2244 snprintf(swonname + 7, 4,
"%03d", nopt);
2245 snprintf(swoffname + 9, 4,
"%03d", nopt);
2247 opt = (opt ==
nullptr) ?
2252 control.id = queryctrl.id;
2253 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2257 queryctrl.name[31] =
'\0';
2260 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2261 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2264 (
int)
sizeof(queryctrl.name), queryctrl.name, (control.value ?
"On" :
"Off"));
2267 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2268 if ((queryctrl.type == V4L2_CTRL_TYPE_MENU) || (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2270 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2274 unsigned int nmenuopt = 0;
2276 snprintf(menuname + 4, 4,
"%03d", nopt);
2277 snprintf(menuoptname + 4, 4,
"%03d", nopt);
2278 menuoptname[7] =
'_';
2280 opt = (opt ==
nullptr) ?
2285 control.id = queryctrl.id;
2286 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2289 querymenu.id = queryctrl.id;
2291 for (querymenu.index = queryctrl.minimum; (
int)querymenu.index <= queryctrl.maximum; querymenu.index++)
2293 if (0 ==
XIOCTL(
fd, VIDIOC_QUERYMENU, &querymenu))
2297 snprintf(menuoptname + 11, 4,
"%03d", nmenuopt);
2298 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2299 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2301 snprintf(sname, 31,
"%.*s", (
int)
sizeof(querymenu.name), querymenu.name);
2304 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2306 snprintf(sname, 19,
"0x%016llX", querymenu.value);
2310 snprintf(sname, 31,
"%.*s", (
int)
sizeof(querymenu.name), querymenu.name);
2314 (
int)
sizeof(sname), sname, (
int)
sizeof(menuoptname), menuoptname, nmenuopt);
2327 queryctrl.name[31] =
'\0';
2331 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2332 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2335 (
int)
sizeof(queryctrl.name), queryctrl.name, control.value);
2341 if (
errno != EINVAL)
2347 perror(
"VIDIOC_QUERYCTRL");
2353 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;; queryctrl.id++)
2355 if (0 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2357 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2359 cerr << queryctrl.name <<
" is disabled." << endl;
2363 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2365 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2368 num_ctrls = (num_ctrls ==
nullptr) ?
2369 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2370 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2375 numbers[nnum].min = queryctrl.minimum;
2376 numbers[nnum].max = queryctrl.maximum;
2377 numbers[nnum].step = queryctrl.step;
2378 numbers[nnum].value = queryctrl.default_value;
2382 control.id = queryctrl.id;
2383 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2384 numbers[nnum].value = control.value;
2387 num_ctrls[nnum] = queryctrl.id;
2388 cerr <<
"Adding ext. " << queryctrl.name <<
" -- min: " << queryctrl.minimum
2389 <<
" max: " << queryctrl.maximum <<
" step: " << queryctrl.step
2390 <<
" value: " << numbers[nnum].value << endl;
2394 if (queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2397 snprintf(optname + 3, 4,
"%03d", nopt);
2398 snprintf(swonname + 7, 4,
"%03d", nopt);
2399 snprintf(swoffname + 9, 4,
"%03d", nopt);
2401 opt = (opt ==
nullptr) ?
2406 control.id = queryctrl.id;
2407 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2411 queryctrl.name[31] =
'\0';
2415 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2416 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2419 (
int)
sizeof(queryctrl.name), queryctrl.name, (control.value ?
"On" :
"Off"));
2422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2423 if ((queryctrl.type == V4L2_CTRL_TYPE_MENU) || (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2425 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2429 unsigned int nmenuopt = 0;
2431 snprintf(menuname + 4, 4,
"%03d", nopt);
2432 snprintf(menuoptname + 4, 4,
"%03d", nopt);
2433 menuoptname[7] =
'_';
2435 opt = (opt ==
nullptr) ?
2440 control.id = queryctrl.id;
2441 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2444 querymenu.id = queryctrl.id;
2446 for (querymenu.index = queryctrl.minimum; (
int)querymenu.index <= queryctrl.maximum; querymenu.index++)
2448 if (0 ==
XIOCTL(
fd, VIDIOC_QUERYMENU, &querymenu))
2452 snprintf(menuoptname + 11, 4,
"%03d", nmenuopt);
2453 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2454 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2456 snprintf(sname, 31,
"%.*s", (
int)
sizeof(querymenu.name), querymenu.name);
2459 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2461 snprintf(sname, 19,
"0x%016llX", querymenu.value);
2465 snprintf(sname, 31,
"%.*s", (
int)
sizeof(querymenu.name), querymenu.name);
2469 (
int)
sizeof(sname), sname, (
int)
sizeof(menuoptname), menuoptname, nmenuopt);
2482 queryctrl.name[31] =
'\0';
2487 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2488 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2491 (
int)
sizeof(queryctrl.name), queryctrl.name, control.value);
2500 for (
int i = 0; i < nnum; i++)
2501 numbers[i].aux0 = &num_ctrls[i];
2513 struct v4l2_control control;
2517 unsigned int * num_ctrls =
nullptr;
2520 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
2522 if (0 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2524 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2526 cerr << queryctrl.name <<
" is disabled." << endl;
2530 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2532 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2535 num_ctrls = (num_ctrls ==
nullptr) ?
2536 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2537 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2539 strncpy(numbers[nnum].name, ((
char *)queryctrl.name),
MAXINDINAME);
2540 strncpy(numbers[nnum].label, ((
char *)queryctrl.name),
MAXINDILABEL);
2542 numbers[nnum].min = queryctrl.minimum;
2543 numbers[nnum].max = queryctrl.maximum;
2544 numbers[nnum].step = queryctrl.step;
2545 numbers[nnum].value = queryctrl.default_value;
2549 control.id = queryctrl.id;
2550 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2551 numbers[nnum].value = control.value;
2554 num_ctrls[nnum] = queryctrl.id;
2557 (
int)
sizeof(queryctrl.name), queryctrl.name, queryctrl.minimum, queryctrl.maximum,
2558 queryctrl.step, numbers[nnum].value);
2563 else if (
errno != EINVAL)
2567 return errno_exit(
"VIDIOC_QUERYCTRL", errmsg);
2571 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;; queryctrl.id++)
2573 if (0 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2575 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2577 cerr << queryctrl.name <<
" is disabled." << endl;
2581 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2583 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2586 num_ctrls = (num_ctrls ==
nullptr) ?
2587 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2588 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2590 strncpy(numbers[nnum].name, ((
char *)queryctrl.name),
MAXINDINAME);
2591 strncpy(numbers[nnum].label, ((
char *)queryctrl.name),
MAXINDILABEL);
2593 numbers[nnum].min = queryctrl.minimum;
2594 numbers[nnum].max = queryctrl.maximum;
2595 numbers[nnum].step = queryctrl.step;
2596 numbers[nnum].value = queryctrl.default_value;
2600 control.id = queryctrl.id;
2601 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2602 numbers[nnum].value = control.value;
2605 num_ctrls[nnum] = queryctrl.id;
2615 for (
int i = 0; i < nnum; i++)
2616 numbers[i].aux0 = &num_ctrls[i];
2624 int V4L2_Base::getControl(
unsigned int ctrl_id,
double * value,
char * errmsg)
2626 struct v4l2_control control;
2629 control.id = ctrl_id;
2631 if (-1 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2632 return errno_exit(
"VIDIOC_G_CTRL", errmsg);
2633 *value = (double)control.value;
2637 int V4L2_Base::setINTControl(
unsigned int ctrl_id,
double new_value,
char * errmsg)
2639 struct v4l2_control control;
2643 queryctrl.id = ctrl_id;
2644 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2646 if ((queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) || (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) ||
2647 (queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE) || (queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE))
2650 (
int)
sizeof(queryctrl.name), queryctrl.name,
2651 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY ?
"read only " :
"",
2652 queryctrl.flags & V4L2_CTRL_FLAG_GRABBED ?
"grabbed " :
"",
2653 queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE ?
"inactive " :
"",
2654 queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE ?
"volatile" :
"");
2662 control.id = ctrl_id;
2663 control.value = (int)new_value;
2664 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CTRL, &control))
2667 (
int)
sizeof(queryctrl.name), queryctrl.name, errmsg);
2668 return errno_exit(
"VIDIOC_S_CTRL", errmsg);
2673 int V4L2_Base::setOPTControl(
unsigned int ctrl_id,
unsigned int new_value,
char * errmsg)
2675 struct v4l2_control control;
2679 queryctrl.id = ctrl_id;
2680 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2682 if ((queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) || (queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) ||
2683 (queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE) || (queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE))
2686 (
int)
sizeof(queryctrl.name), queryctrl.name,
2687 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY ?
"read only " :
"",
2688 queryctrl.flags & V4L2_CTRL_FLAG_GRABBED ?
"grabbed " :
"",
2689 queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE ?
"inactive " :
"",
2690 queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE ?
"volatile" :
"");
2698 control.id = ctrl_id;
2699 control.value = new_value;
2700 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CTRL, &control))
2703 (
int)
sizeof(queryctrl.name), queryctrl.name, errmsg);
2704 return errno_exit(
"VIDIOC_S_CTRL", errmsg);
2709 bool V4L2_Base::enumerate_ext_ctrl()
2715 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2716 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2719 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2720 while (0 ==
XIOCTL(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2722 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2724 cerr <<
"DISABLED--Control " << queryctrl.name << endl;
2725 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2729 if (queryctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
2731 cerr <<
"Control Class " << queryctrl.name << endl;
2732 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2736 cerr <<
"Control " << queryctrl.name << endl;
2738 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2739 if ((queryctrl.type == V4L2_CTRL_TYPE_MENU) || (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2741 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2744 if (queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2745 cerr <<
" boolean" << endl;
2746 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2747 cerr <<
" integer" << endl;
2750 if (queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2751 cerr <<
" button" << endl;
2752 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2760 unsigned int * noptions,
const char * dev,
const char * group)
2762 struct v4l2_control control;
2765 unsigned int * num_ctrls =
nullptr;
2768 unsigned int nopt = 0;
2769 char optname[] =
"OPT000";
2770 char swonname[] =
"SET_OPT000";
2771 char swoffname[] =
"UNSET_OPT000";
2772 char menuname[] =
"MENU000";
2773 char menuoptname[] =
"MENU000_OPT000";
2779 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2780 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2784 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2785 while (0 ==
XIOCTL(
fd, VIDIOC_QUERYCTRL, &queryctrl))
2787 if (queryctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
2791 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2795 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2799 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2803 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2805 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2808 num_ctrls = (num_ctrls ==
nullptr) ? (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2809 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2814 numbers[nnum].min = queryctrl.minimum;
2815 numbers[nnum].max = queryctrl.maximum;
2816 numbers[nnum].step = queryctrl.step;
2817 numbers[nnum].value = queryctrl.default_value;
2821 control.id = queryctrl.id;
2822 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2823 numbers[nnum].value = control.value;
2826 num_ctrls[nnum] = queryctrl.id;
2829 (
int)
sizeof(queryctrl.name), queryctrl.name, queryctrl.minimum, queryctrl.maximum,
2830 queryctrl.step, numbers[nnum].value);
2834 if (queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2837 snprintf(optname + 3, 4,
"%03d", nopt);
2838 snprintf(swonname + 7, 4,
"%03d", nopt);
2839 snprintf(swoffname + 9, 4,
"%03d", nopt);
2845 control.id = queryctrl.id;
2846 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2851 (sw + 1)->aux =
nullptr;
2852 queryctrl.name[31] =
'\0';
2855 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2856 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2859 queryctrl.name, (control.value ?
"On" :
"Off"));
2862 if (queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2865 snprintf(optname + 3, 4,
"%03d", nopt);
2866 snprintf(swonname + 7, 4,
"%03d", nopt);
2872 queryctrl.name[31] =
'\0';
2877 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2878 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2883 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2884 if ((queryctrl.type == V4L2_CTRL_TYPE_MENU) || (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2886 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2890 unsigned int nmenuopt = 0;
2892 snprintf(menuname + 4, 4,
"%03d", nopt);
2893 snprintf(menuoptname + 4, 4,
"%03d", nopt);
2894 menuoptname[7] =
'_';
2900 control.id = queryctrl.id;
2901 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2904 querymenu.id = queryctrl.id;
2906 for (querymenu.index = queryctrl.minimum; (
int)querymenu.index <= queryctrl.maximum; querymenu.index++)
2908 if (0 ==
XIOCTL(
fd, VIDIOC_QUERYMENU, &querymenu))
2912 snprintf(menuoptname + 11, 4,
"%03d", nmenuopt);
2913 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2914 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
2916 snprintf(sname, 31,
"%.*s", (
int)
sizeof(querymenu.name), querymenu.name);
2919 if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2921 snprintf(sname, 19,
"0x%016llX", querymenu.value);
2925 snprintf(sname, 31,
"%.*s", (
int)
sizeof(querymenu.name), querymenu.name);
2929 (
int)
sizeof(sname), sname, (
int)
sizeof(menuoptname), menuoptname, nmenuopt,
2934 sw[nmenuopt].aux = malloc(
sizeof(
unsigned int));
2935 *(
unsigned int *)(sw[nmenuopt].aux) = (querymenu.index);
2945 queryctrl.name[31] =
'\0';
2948 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2949 *(
unsigned int *)(opt[nopt].aux) = (queryctrl.id);
2952 (
int)
sizeof(queryctrl.name), queryctrl.name, control.value);
2961 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2965 for (
int i = 0; i < nnum; i++)
2966 numbers[i].aux0 = &num_ctrls[i];
2978 void V4L2_Base::setDeviceName(
const char * name)
2991 std::map<std::string, std::string> V4L2_Base::enumerate()
2993 std::map<std::string, std::string> devices;
2995 auto searchPath = [&](std::string prefix)
2997 struct dirent **namelist;
2998 std::vector<std::string> detectedDevices;
3000 devCount = scandir(prefix.c_str(), &namelist, video_dev_file_select, alphasort);
3005 if (detectedDevices.size() < 10)
3007 std::string s(namelist[devCount]->d_name);
3008 s.erase(s.find_last_not_of(
" \n\r\t") + 1);
3009 detectedDevices.push_back(prefix + s);
3011 free(namelist[devCount]);
3016 return detectedDevices;
3019 const std::vector<std::string> videoDevices = searchPath(
"/dev/");
3021 for (
const auto &oneDevice : videoDevices)
3023 int fd = open(oneDevice.c_str(), O_RDWR | O_NONBLOCK, 0);
3026 struct v4l2_capability cap;
3027 if (ioctl(
fd, VIDIOC_QUERYCAP, &cap) >= 0)
3029 devices[std::string(
reinterpret_cast<const char *
>(cap.card))] = oneDevice;
3041 int V4L2_Base::video_dev_file_select(
const dirent * entry)
3043 static const char *filter_names[] = {
"video",
nullptr };
3044 const char **filter;
3046 for (filter = filter_names; *filter; ++filter)
3048 if (strstr(entry->d_name, *filter) !=
nullptr)
void IERmCallback(int callbackid)
Remove a callback function.
int IEAddCallback(int readfiledes, IE_CBF *fp, void *p)
Register a new callback, fp, to be called with userpointer as argument when readfiledes is ready.
Public interface to INDI's eventloop mechanism.
void() WPF(void *)
Signature of a work procedure function.
struct _ISwitchVectorProperty ISwitchVectorProperty
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Interface to the reference INDI C API device implementation on the Device Driver side.
#define DEBUGDEVICE(device, priority, msg)
#define DEBUGFDEVICE(device, priority, msg,...)
char * entityXML(char *s)
return a string with all xml-sensitive characters within the passed string replaced with their entity...
A little DOM-style library to handle parsing and processing an XML file.
Namespace to encapsulate INDI client, drivers, and mediator classes.
const char * getDeviceName()
Number vector property descriptor.
Switch vector property descriptor.
#define XIOCTL(fd, ioctl, arg)