53#include <linux/version.h>
54#elif defined(__FreeBSD__) || defined(__OpenBSD__)
55#define LINUX_VERSION_CODE 1
56#define KERNEL_VERSION(...) 1
61#define CLEAR(x) memset(&(x), 0, sizeof(x))
63#define XIOCTL(fd, ioctl, arg) xioctl(fd, ioctl, arg, #ioctl)
65#define DBG_STR_PIX "%c%c%c%c"
66#define DBG_PIX(pf) ((pf) >> 0) & 0xFF, ((pf) >> 8) & 0xFF, ((pf) >> 16) & 0xFF, ((pf) >> 24) & 0xFF
75#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
76#define DBG_STR_FLAGS "...%c .%c%c%c %c%c.%c .%c%c%c %c%c%c%c"
78 ((b).flags & V4L2_BUF_FLAG_TSTAMP_SRC_SOE) ? 'S' : 'E', \
79 ((b).flags & V4L2_BUF_FLAG_TIMESTAMP_COPY) ? 'c' : '.', \
80 ((b).flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) ? 'm' : '.', \
81 ((b).flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN) ? 'C' : '.', \
82 ((b).flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE) ? 'I' : '.', \
83 ((b).flags & V4L2_BUF_FLAG_PREPARED) ? 'p' : '.', \
84 ((b).flags & V4L2_BUF_FLAG_TIMECODE) ? 'T' : '.', \
85 ((b).flags & V4L2_BUF_FLAG_ERROR) ? 'E' : '.', \
86 ((b).flags & V4L2_BUF_FLAG_BFRAME) ? 'B' : '.', \
87 ((b).flags & V4L2_BUF_FLAG_PFRAME) ? 'P' : '.', \
88 ((b).flags & V4L2_BUF_FLAG_KEYFRAME) ? 'K' : '.', \
89 ((b).flags & V4L2_BUF_FLAG_DONE) ? 'd' : '.', \
90 ((b).flags & V4L2_BUF_FLAG_QUEUED) ? 'q' : '.', \
91 ((b).flags & V4L2_BUF_FLAG_MAPPED) ? 'm' : '.'
93#define DBG_STR_FLAGS "%s"
94#define DBG_FLAGS(b) ""
97#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
98#define DBG_STR_FMT "%ux%u " DBG_STR_PIX " %scompressed (%ssupported)"
100 (f).fmt.pix.width, (f).fmt.pix.height, DBG_PIX((f).fmt.pix.pixelformat), \
101 ((f).fmt.pix.flags & V4L2_FMT_FLAG_COMPRESSED) ? "" : "un", \
102 (decoder->issupportedformat((f).fmt.pix.pixelformat) ? "" : "un")
104#define DBG_STR_FMT "%ux%u " DBG_STR_PIX " (%ssupported)"
106 (f).fmt.pix.width, (f).fmt.pix.height, DBG_PIX((f).fmt.pix.pixelformat), \
107 (decoder->issupportedformat((f).fmt.pix.pixelformat) ? "" : "un")
110#define DBG_STR_BUF "#%d " DBG_STR_FLAGS " % 7d bytes %4.4s seq %d:%d stamp %ld.%06ld"
112 (b).index, DBG_FLAGS(b), (b).bytesused, \
113 ((b).memory == V4L2_MEMORY_MMAP) ? \
115 ((b).memory == V4L2_MEMORY_USERPTR) ? "uptr" : \
116 ((b).memory == 4 ) ? \
118 ((b).memory == V4L2_MEMORY_OVERLAY) ? "over" : "", \
119 (b).sequence, (b).field, (b).timestamp.tv_sec, (b).timestamp.tv_usec
168 "Using default decoder '%s'\n Supported V4L2 formats are:",
decoder->
getName());
169 for (std::vector<unsigned int>::const_iterator it = vsuppformats.begin(); it != vsuppformats.end(); ++it)
205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
206 switch (
fmt.fmt.pix.pixelformat)
208 case V4L2_PIX_FMT_JPEG:
209 case V4L2_PIX_FMT_MJPEG:
211 __FUNCTION__,
fmt.fmt.pix.pixelformat,
fmt.fmt.pix.pixelformat >> 8,
212 fmt.fmt.pix.pixelformat >> 16,
fmt.fmt.pix.pixelformat >> 24);
217 __FUNCTION__,
fmt.fmt.pix.pixelformat,
fmt.fmt.pix.pixelformat >> 8,
218 fmt.fmt.pix.pixelformat >> 16,
fmt.fmt.pix.pixelformat >> 24,
219 fmt.fmt.pix.flags & V4L2_FMT_FLAG_COMPRESSED);
220 return fmt.fmt.pix.flags & V4L2_FMT_FLAG_COMPRESSED;
223 switch (
fmt.fmt.pix.pixelformat)
225 case V4L2_PIX_FMT_GREY:
252 r = ioctl(
fd, request, arg);
254 while (-1 == r && EINTR ==
errno);
258 request, request_str,
errno, strerror(
errno));
308 if (-1 ==
XIOCTL(
fd, VIDIOC_TRY_FMT, &new_fmt))
311 __FUNCTION__,
DBG_FMT(new_fmt));
319 if (-1 ==
XIOCTL(
fd, VIDIOC_S_FMT, &new_fmt))
329 new_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
330 if (-1 ==
XIOCTL(
fd, VIDIOC_G_FMT, &new_fmt))
352 fprintf(stderr,
"%s error %d, %s\n", s,
errno, strerror(
errno));
410 if (!(strcmp((
const char *)
cap.driver,
"pwc")))
478 cerr <<
"in read Frame method read" << endl;
499 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
500 buf.memory = V4L2_MEMORY_MMAP;
513 "%s: invalid buffer query, doing as if buffer was in output queue",
518 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QUERYBUF", errmsg);
530 "%s: no buffer found with DQBUF ioctl (EAGAIN) - frame not ready or not requested",
538 "%s: transitory internal error with DQBUF ioctl (EIO)", __FUNCTION__);
544 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_DQBUF", errmsg);
550 if (
buf.flags & V4L2_BUF_FLAG_ERROR)
553 "%s: recoverable error with DQBUF ioctl (BUF_FLAG_ERROR) - frame should be dropped",
556 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QBUF", errmsg);
564 "%s: frame is %d-byte long, expected %d - frame should be dropped", __FUNCTION__,
565 buf.bytesused,
fmt.fmt.pix.sizeimage);
569 unsigned char const * b = (
unsigned char const *)
buffers[
buf.index].
start;
570 unsigned char const * end = b +
buf.bytesused;
574 "%s: [%p] %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
575 __FUNCTION__, b, b[0 * 4 + 0], b[0 * 4 + 1], b[0 * 4 + 2], b[0 * 4 + 3],
576 b[1 * 4 + 0], b[1 * 4 + 1], b[1 * 4 + 2], b[1 * 4 + 3], b[2 * 4 + 0], b[2 * 4 + 1],
577 b[2 * 4 + 2], b[2 * 4 + 3], b[3 * 4 + 0], b[3 * 4 + 1], b[3 * 4 + 2],
579 while ((b += 16) < end);
583 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QBUF", errmsg);
588#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
590 switch (
buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MASK)
592 case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN:
594 case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC:
596 struct timespec uptime = { 0, 0 };
597 clock_gettime(CLOCK_MONOTONIC, &uptime);
599 struct timeval epochtime = { 0, 0 };
603 (epochtime.tv_sec - uptime.tv_sec +
buf.timestamp.tv_sec) +
604 (epochtime.tv_usec - uptime.tv_nsec / 1000.0f +
buf.timestamp.tv_usec) / 1000000.0f;
606 if (V4L2_BUF_FLAG_TSTAMP_SRC_SOE == (
buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK))
609 "%s: frame exposure started %.03f seconds ago", __FUNCTION__, -secs);
611 else if (V4L2_BUF_FLAG_TSTAMP_SRC_EOF == (
buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK))
614 "%s: frame finished capturing %.03f seconds ago", __FUNCTION__, -secs);
623 case V4L2_BUF_FLAG_TIMESTAMP_COPY:
653 return errno_exit(
"ReadFrame IO_METHOD_MMAP: VIDIOC_QBUF", errmsg);
669 cerr <<
"in read Frame method userptr" << endl;
672 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
673 buf.memory = V4L2_MEMORY_USERPTR;
698 errno_exit(
"ReadFrame IO_METHOD_USERPTR: VIDIOC_QBUF", errmsg);
708 enum v4l2_buf_type
type;
725 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
733 return errno_exit(
"VIDIOC_STREAMOFF", errmsg);
744 enum v4l2_buf_type
type;
758 struct v4l2_buffer
buf;
762 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
763 buf.memory = V4L2_MEMORY_MMAP;
771 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
783 struct v4l2_buffer
buf;
787 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
788 buf.memory = V4L2_MEMORY_USERPTR;
789 buf.m.userptr = (
unsigned long)
buffers[i].start;
793 return errno_exit(
"StartCapturing IO_METHOD_USERPTR: VIDIOC_QBUF", errmsg);
796 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
825 for (
unsigned int i = 0; i <
n_buffers; ++i)
831 for (
unsigned int i = 0; i <
n_buffers; ++i)
847 fprintf(stderr,
"Out of memory\n");
856 fprintf(stderr,
"Out of memory\n");
863 struct v4l2_requestbuffers req;
869 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
870 req.memory = V4L2_MEMORY_MMAP;
872 if (-1 ==
XIOCTL(
fd, VIDIOC_REQBUFS, &req))
876 fprintf(stderr,
"%.*s does not support memory mapping\n", (
int)
sizeof(
dev_name),
dev_name);
888 fprintf(stderr,
"Insufficient buffer memory on %.*s\n", (
int)
sizeof(
dev_name),
dev_name);
897 fprintf(stderr,
"buffers. Out of memory\n");
898 strncpy(errmsg,
"buffers. Out of memory\n",
ERRMSGSIZ);
904 struct v4l2_buffer
buf;
908 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
909 buf.memory = V4L2_MEMORY_MMAP;
917 MAP_SHARED ,
fd,
buf.m.offset);
928 struct v4l2_requestbuffers req;
934 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
935 req.memory = V4L2_MEMORY_USERPTR;
937 if (-1 ==
XIOCTL(
fd, VIDIOC_REQBUFS, &req))
941 fprintf(stderr,
"%.*s does not support user pointer i/o\n", (
int)
sizeof(
dev_name),
dev_name);
954 fprintf(stderr,
"Out of memory\n");
965 fprintf(stderr,
"Out of memory\n");
973 struct v4l2_input input_avail;
979 fprintf(stderr,
"%.*s is no V4L2 device\n", (
int)
sizeof(
dev_name),
dev_name);
990 cap.driver, (
cap.version >> 16) & 0xFF, (
cap.version >> 8) & 0xFF, (
cap.version & 0xFF));
1012 if (
cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
1014 if (
cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
1016 if (
cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
1018 if (
cap.capabilities & V4L2_CAP_VBI_CAPTURE)
1020 if (
cap.capabilities & V4L2_CAP_VBI_OUTPUT)
1022 if (
cap.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE)
1024 if (
cap.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
1026 if (
cap.capabilities & V4L2_CAP_RDS_CAPTURE)
1028 if (
cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
1030 if (
cap.capabilities & V4L2_CAP_TUNER)
1032 if (
cap.capabilities & V4L2_CAP_AUDIO)
1034 if (
cap.capabilities & V4L2_CAP_RADIO)
1036 if (
cap.capabilities & V4L2_CAP_READWRITE)
1038 if (
cap.capabilities & V4L2_CAP_ASYNCIO)
1040 if (
cap.capabilities & V4L2_CAP_STREAMING)
1046 if (!(
cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
1048 fprintf(stderr,
"%.*s is no video capture device\n", (
int)
sizeof(
dev_name),
dev_name);
1056 if (!(
cap.capabilities & V4L2_CAP_READWRITE))
1058 fprintf(stderr,
"%.*s does not support read i/o", (
int)
sizeof(
dev_name),
dev_name);
1066 if (!(
cap.capabilities & V4L2_CAP_STREAMING))
1068 fprintf(stderr,
"%.*s does not support streaming i/o", (
int)
sizeof(
dev_name),
dev_name);
1078 if (-1 == ioctl(
fd, VIDIOC_G_INPUT, &
input.index))
1080 perror(
"VIDIOC_G_INPUT");
1085 for (input_avail.index = 0; ioctl(
fd, VIDIOC_ENUMINPUT, &input_avail) != -1; input_avail.index++)
1087 (
int)
sizeof(input_avail.name), input_avail.name,
1088 (input_avail.type == V4L2_INPUT_TYPE_TUNER ?
"Tuner/RF Demodulator" :
"Composite/S-Video"),
1089 input.index == input_avail.index ?
" current" :
"");
1090 if (
errno != EINVAL)
1095 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1099 perror(
"VIDIOC_CROPCAP");
1107 " Crop capabilities: bounds = (top=%d, left=%d, width=%d, height=%d)",
cropcap.bounds.top,
1110 " Crop capabilities: defrect = (top=%d, left=%d, width=%d, height=%d)",
cropcap.defrect.top,
1121 perror(
"VIDIOC_S_CROP");
1127 perror(
"VIDIOC_G_CROP");
1137 struct v4l2_fmtdesc fmt_avail;
1138 fmt_avail.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1141 for (fmt_avail.index = 0; ioctl(
fd, VIDIOC_ENUM_FMT, &fmt_avail) != -1; fmt_avail.index++)
1146 (
int)
sizeof(fmt_avail.description), fmt_avail.description, (fmt_avail.pixelformat) & 0xFF,
1147 (fmt_avail.pixelformat >> 8) & 0xFF, (fmt_avail.pixelformat >> 16) & 0xFF,
1148 (fmt_avail.pixelformat >> 24) & 0xFF,
1152 struct v4l2_frmsizeenum frm_sizeenum;
1153 frm_sizeenum.pixel_format = fmt_avail.pixelformat;
1155 " Enumerating available Frame sizes/rates for this format:");
1156 for (frm_sizeenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMESIZES, &frm_sizeenum) != -1;
1157 frm_sizeenum.index++)
1159 switch (frm_sizeenum.type)
1161 case V4L2_FRMSIZE_TYPE_DISCRETE:
1163 " %2d. (Discrete) width %d x height %d\n", frm_sizeenum.index,
1164 frm_sizeenum.discrete.width, frm_sizeenum.discrete.height);
1166 case V4L2_FRMSIZE_TYPE_STEPWISE:
1168 " (Stepwise) min. width %d, max. width %d step width %d",
1169 frm_sizeenum.stepwise.min_width, frm_sizeenum.stepwise.max_width,
1170 frm_sizeenum.stepwise.step_width);
1172 " (Stepwise) min. height %d, max. height %d step height %d ",
1173 frm_sizeenum.stepwise.min_height, frm_sizeenum.stepwise.max_height,
1174 frm_sizeenum.stepwise.step_height);
1176 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1178 " (Continuous--step=1) min. width %d, max. width %d",
1179 frm_sizeenum.stepwise.min_width, frm_sizeenum.stepwise.max_width);
1181 " (Continuous--step=1) min. height %d, max. height %d ",
1182 frm_sizeenum.stepwise.min_height, frm_sizeenum.stepwise.max_height);
1191 struct v4l2_frmivalenum frmi_valenum;
1192 frmi_valenum.pixel_format = fmt_avail.pixelformat;
1193 if (frm_sizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE)
1195 frmi_valenum.width = frm_sizeenum.discrete.width;
1196 frmi_valenum.height = frm_sizeenum.discrete.height;
1200 frmi_valenum.width = frm_sizeenum.stepwise.max_width;
1201 frmi_valenum.height = frm_sizeenum.stepwise.max_height;
1203 frmi_valenum.type = 0;
1204 frmi_valenum.stepwise.min.numerator = 0;
1205 frmi_valenum.stepwise.min.denominator = 0;
1206 frmi_valenum.stepwise.max.numerator = 0;
1207 frmi_valenum.stepwise.max.denominator = 0;
1208 frmi_valenum.stepwise.step.numerator = 0;
1209 frmi_valenum.stepwise.step.denominator = 0;
1211 for (frmi_valenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmi_valenum) != -1;
1212 frmi_valenum.index++)
1214 switch (frmi_valenum.type)
1216 case V4L2_FRMIVAL_TYPE_DISCRETE:
1218 frmi_valenum.discrete.numerator, frmi_valenum.discrete.denominator);
1220 case V4L2_FRMIVAL_TYPE_STEPWISE:
1223 " (Stepwise) min. %d/%ds, max. %d / %d s, step %d / %d s",
1224 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1225 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator,
1226 frmi_valenum.stepwise.step.numerator, frmi_valenum.stepwise.step.denominator);
1228 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1231 " (Continuous) min. %d / %d s, max. %d / %d s",
1232 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1233 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator);
1237 " Unknown Frame rate type: %d", frmi_valenum.type);
1241 if (frmi_valenum.index == 0)
1243 perror(
"VIDIOC_ENUM_FRAMEINTERVALS");
1244 switch (frmi_valenum.type)
1246 case V4L2_FRMIVAL_TYPE_DISCRETE:
1248 frmi_valenum.discrete.numerator, frmi_valenum.discrete.denominator);
1250 case V4L2_FRMIVAL_TYPE_STEPWISE:
1253 " (Stepwise) min. %d/%ds, max. %d / %d s, step %d / %d s",
1254 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1255 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator,
1256 frmi_valenum.stepwise.step.numerator, frmi_valenum.stepwise.step.denominator);
1258 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1261 " (Continuous) min. %d / %d s, max. %d / %d s",
1262 frmi_valenum.stepwise.min.numerator, frmi_valenum.stepwise.min.denominator,
1263 frmi_valenum.stepwise.max.numerator, frmi_valenum.stepwise.max.denominator);
1267 " Unknown Frame rate type: %d", frmi_valenum.type);
1276 if (
errno != EINVAL)
1341 if (-1 == close(
fd))
1351 snprintf(
dev_name, 64,
"%s", devpath);
1361 if (!S_ISCHR(st.st_mode))
1379 snprintf(errmsg,
ERRMSGSIZ,
"%s\n", strerror(0));
1392 struct v4l2_input input_avail;
1399 memset(inputs, 0, inputsLen);
1402 for (input_avail.index = 0; (int)input_avail.index <
enumeratedInputs; input_avail.index++)
1405 if (
XIOCTL(
fd, VIDIOC_ENUMINPUT, &input_avail))
1409 snprintf(inputs[input_avail.index].name,
MAXINDINAME,
"%s", (
const char *)input_avail.name);
1410 snprintf(inputs[input_avail.index].label,
MAXINDILABEL,
"%s", (
const char *)input_avail.name);
1418 inputssp->
sp = inputs;
1419 inputssp->
nsp = input_avail.index;
1426 (
int)
sizeof(inputs[
input.index].name), inputs[
input.index].name);
1443 if (-1 ==
XIOCTL(
fd, VIDIOC_S_INPUT, &inputindex))
1461 if (!captureformatssp)
1464 struct v4l2_fmtdesc fmt_avail;
1471 memset(formats, 0, formatsLen);
1474 fmt_avail.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1478 if (
XIOCTL(
fd, VIDIOC_ENUM_FMT, &fmt_avail))
1482 snprintf(formats[fmt_avail.index].name,
MAXINDINAME,
"%s", (
const char *)fmt_avail.description);
1483 snprintf(formats[fmt_avail.index].label,
MAXINDILABEL,
"%s", (
const char *)fmt_avail.description);
1487 formats[fmt_avail.index].aux = (
int *)malloc(
sizeof(
int));
1488 if (!formats[fmt_avail.index].aux)
1490 *(
int *)formats[fmt_avail.index].aux = fmt_avail.pixelformat;
1494 if (captureformatssp->
sp)
1495 free(captureformatssp->
sp);
1498 captureformatssp->
sp = formats;
1499 captureformatssp->
nsp = fmt_avail.index;
1503 for (
unsigned int i = 0; i < fmt_avail.index; i++)
1505 if ((
int)
fmt.fmt.pix.pixelformat == *(
int *)formats[i].aux)
1509 (
fmt.fmt.pix.pixelformat) & 0xFF, (
fmt.fmt.pix.pixelformat >> 8) & 0xFF,
1510 (
fmt.fmt.pix.pixelformat >> 16) & 0xFF, (
fmt.fmt.pix.pixelformat >> 24) & 0xFF);
1525 struct v4l2_format new_fmt;
1528 new_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1529 new_fmt.fmt.pix.pixelformat = captureformat;
1536 struct v4l2_frmsizeenum frm_sizeenum;
1538 INumber * sizevalue =
nullptr;
1539 bool sizefound =
false;
1544 if (capturesizessp->
sp)
1545 free(capturesizessp->
sp);
1546 if (capturesizenp->
np)
1547 free(capturesizenp->
np);
1549 frm_sizeenum.pixel_format =
fmt.fmt.pix.pixelformat;
1551 for (frm_sizeenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMESIZES, &frm_sizeenum) != -1; frm_sizeenum.index++)
1553 switch (frm_sizeenum.type)
1555 case V4L2_FRMSIZE_TYPE_DISCRETE:
1556 sizes = (sizes ==
nullptr) ? (
ISwitch *)malloc(
sizeof(
ISwitch)) :
1557 (
ISwitch *)realloc(sizes, (frm_sizeenum.index + 1) *
sizeof(
ISwitch));
1559 snprintf(sizes[frm_sizeenum.index].name,
MAXINDINAME,
"%dx%d", frm_sizeenum.discrete.width,
1560 frm_sizeenum.discrete.height);
1561 snprintf(sizes[frm_sizeenum.index].label,
MAXINDINAME,
"%dx%d", frm_sizeenum.discrete.width,
1562 frm_sizeenum.discrete.height);
1563 sizes[frm_sizeenum.index].s =
ISS_OFF;
1566 if ((
fmt.fmt.pix.width == frm_sizeenum.discrete.width) &&
1567 (
fmt.fmt.pix.height == frm_sizeenum.discrete.height))
1569 sizes[frm_sizeenum.index].s =
ISS_ON;
1572 frm_sizeenum.index, frm_sizeenum.discrete.width, frm_sizeenum.discrete.height);
1576 case V4L2_FRMSIZE_TYPE_STEPWISE:
1577 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1579 IUFillNumber(sizevalue,
"Width",
"Width",
"%.0f", frm_sizeenum.stepwise.min_width,
1580 frm_sizeenum.stepwise.max_width, frm_sizeenum.stepwise.step_width,
fmt.fmt.pix.width);
1581 IUFillNumber(sizevalue + 1,
"Height",
"Height",
"%.0f", frm_sizeenum.stepwise.min_height,
1582 frm_sizeenum.stepwise.max_height, frm_sizeenum.stepwise.step_height,
fmt.fmt.pix.height);
1584 fmt.fmt.pix.height);
1592 if (sizes !=
nullptr)
1594 capturesizessp->
sp = sizes;
1595 capturesizessp->
nsp = frm_sizeenum.index;
1596 capturesizenp->
np =
nullptr;
1600 capturesizenp->
np = sizevalue;
1601 capturesizenp->
nnp = 2;
1602 capturesizessp->
sp =
nullptr;
1615 struct v4l2_format new_fmt =
fmt;
1617 new_fmt.fmt.pix.width = w;
1618 new_fmt.fmt.pix.height = h;
1625 struct v4l2_frmivalenum frmi_valenum;
1627 INumber * ratevalue =
nullptr;
1628 struct v4l2_fract frate;
1630 if (frameratessp->
sp)
1631 free(frameratessp->
sp);
1632 if (frameratenp->
np)
1633 free(frameratenp->
np);
1636 bzero(&frmi_valenum,
sizeof(frmi_valenum));
1637 frmi_valenum.pixel_format =
fmt.fmt.pix.pixelformat;
1638 frmi_valenum.width =
fmt.fmt.pix.width;
1639 frmi_valenum.height =
fmt.fmt.pix.height;
1641 for (frmi_valenum.index = 0;
XIOCTL(
fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmi_valenum) != -1; frmi_valenum.index++)
1643 switch (frmi_valenum.type)
1645 case V4L2_FRMIVAL_TYPE_DISCRETE:
1646 rates = (rates ==
nullptr) ? (
ISwitch *)malloc(
sizeof(
ISwitch)) :
1647 (
ISwitch *)realloc(rates, (frmi_valenum.index + 1) *
sizeof(
ISwitch));
1648 snprintf(rates[frmi_valenum.index].name,
MAXINDINAME,
"%d/%d", frmi_valenum.discrete.numerator,
1649 frmi_valenum.discrete.denominator);
1650 snprintf(rates[frmi_valenum.index].label,
MAXINDINAME,
"%d/%d", frmi_valenum.discrete.numerator,
1651 frmi_valenum.discrete.denominator);
1652 if ((frate.numerator == frmi_valenum.discrete.numerator) &&
1653 (frate.denominator == frmi_valenum.discrete.denominator))
1656 frmi_valenum.discrete.numerator, frmi_valenum.discrete.denominator);
1657 rates[frmi_valenum.index].s =
ISS_ON;
1660 rates[frmi_valenum.index].s =
ISS_OFF;
1662 case V4L2_FRMIVAL_TYPE_STEPWISE:
1663 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1665 IUFillNumber(ratevalue,
"V4L2_FRAME_INTERVAL",
"Frame Interval",
"%.0f",
1666 frmi_valenum.stepwise.min.numerator / (
double)frmi_valenum.stepwise.min.denominator,
1667 frmi_valenum.stepwise.max.numerator / (
double)frmi_valenum.stepwise.max.denominator,
1668 frmi_valenum.stepwise.step.numerator / (
double)frmi_valenum.stepwise.step.denominator,
1669 frate.numerator / (
double)frate.denominator);
1676 frameratessp->
sp =
nullptr;
1677 frameratessp->
nsp = 0;
1678 frameratenp->
np =
nullptr;
1679 frameratenp->
nnp = 0;
1680 if (frmi_valenum.index != 0)
1682 if (rates !=
nullptr)
1684 frameratessp->
sp = rates;
1685 frameratessp->
nsp = frmi_valenum.index;
1689 frameratenp->
np = ratevalue;
1690 frameratenp->
nnp = 1;
1698 if (x == 0 && y == 0 && w == (
int)
fmt.fmt.pix.width && h == (
int)
fmt.fmt.pix.height)
1705 int const pix_width =
static_cast <int> (
fmt.fmt.pix.width);
1706 int const pix_height =
static_cast <int> (
fmt.fmt.pix.height);
1709 crop.c.left = 0 <= x ? x < pix_width ? x : pix_width - 1 : 0;
1710 crop.c.top = 0 <= y ? y < pix_height ? y : pix_height - 1 : 0;
1711 crop.c.width = 0 <= w ? w < pix_width ? w : pix_width : 0;
1712 crop.c.height = 0 <= h ? h < pix_height ? h : pix_height : 0;
1715 if (x + w < 0 || y + h < 0 || pix_width <= x || pix_height <= y)
1717 strncpy(errmsg,
"requested crop rectangle is outside of frame",
ERRMSGSIZ);
1734 if (0 + pix_width < x + w)
1738 if (0 + pix_height < y + h)
1744 struct v4l2_crop software_crop;
1745 software_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1746 software_crop.c.left = x;
1747 software_crop.c.top = y;
1748 software_crop.c.width = w;
1749 software_crop.c.height = h;
1755 struct v4l2_crop hardware_crop = software_crop;
1760 hardware_crop.c.top--;
1761 hardware_crop.c.height++;
1767 hardware_crop.c.height++;
1771 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CROP, &hardware_crop))
1774 "Failed V4L2 hardware crop request 0x%08X (%dx%d at (%d, %d)), falling back to software crop",
1775 (
unsigned int)VIDIOC_S_CROP, hardware_crop.c.width, hardware_crop.c.height,
1776 hardware_crop.c.left, hardware_crop.c.top);
1779 else if (-1 ==
XIOCTL(
fd, VIDIOC_G_CROP, &hardware_crop))
1786 (
unsigned int)VIDIOC_S_CROP, hardware_crop.c.width, hardware_crop.c.height,
1787 hardware_crop.c.left, hardware_crop.c.top);
1797 strncpy(errmsg,
"No hardware and software cropping for this format",
ERRMSGSIZ);
1803 crop = software_crop;
1813 return crop.c.width;
1815 return fmt.fmt.pix.width;
1821 return crop.c.height;
1823 return fmt.fmt.pix.height;
1833 return fmt.fmt.pix.pixelformat;
1843 struct v4l2_streamparm sparm;
1845 bzero(&sparm,
sizeof(
struct v4l2_streamparm));
1846 sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1847 sparm.parm.capture.timeperframe = frate;
1848 if (-1 ==
XIOCTL(
fd, VIDIOC_S_PARM, &sparm))
1864 int const fps = frate.denominator / frate.numerator;
1866 struct v4l2_format new_fmt =
fmt;
1870 return errno_exit(
"pwcsetframerate", errmsg);
1879 struct v4l2_streamparm sparm;
1881 bzero(&sparm,
sizeof(
struct v4l2_streamparm));
1882 sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1883 if (-1 ==
XIOCTL(
fd, VIDIOC_G_PARM, &sparm))
1885 perror(
"VIDIOC_G_PARM");
1889 frameRate = sparm.parm.capture.timeperframe;
1898 return ((
char *)
cap.card);
1918 struct v4l2_format new_fmt =
fmt;
1920 new_fmt.fmt.pix.width = x;
1921 new_fmt.fmt.pix.height = y;
1983 struct v4l2_format tryfmt;
1989 tryfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1990 tryfmt.fmt.pix.width = 10;
1991 tryfmt.fmt.pix.height = 10;
1992 tryfmt.fmt.pix.pixelformat =
fmt.fmt.pix.pixelformat;
1993 tryfmt.fmt.pix.field =
fmt.fmt.pix.field;
1995 if (-1 ==
XIOCTL(
fd, VIDIOC_TRY_FMT, &tryfmt))
2001 xmin = tryfmt.fmt.pix.width;
2002 ymin = tryfmt.fmt.pix.height;
2004 tryfmt.fmt.pix.width = 1600;
2005 tryfmt.fmt.pix.height = 1200;
2007 if (-1 ==
XIOCTL(
fd, VIDIOC_TRY_FMT, &tryfmt))
2013 xmax = tryfmt.fmt.pix.width;
2014 ymax = tryfmt.fmt.pix.height;
2016 cerr <<
"Min X: " <<
xmin <<
" - Max X: " <<
xmax <<
" - Min Y: " <<
ymin <<
" - Max Y: " <<
ymax << endl;
2028 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2030 cerr <<
"DISABLED--Control " <<
queryctrl.name << endl;
2033 cerr <<
"Control " <<
queryctrl.name << endl;
2034#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2035 if ((
queryctrl.type == V4L2_CTRL_TYPE_MENU) || (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2037 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2040 if (
queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2041 cerr <<
" boolean" << endl;
2042 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2043 cerr <<
" integer" << endl;
2046 if (
queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2047 cerr <<
" button" << endl;
2051 if (
errno == EINVAL)
2063 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2065 cerr <<
"DISABLED--Private Control " <<
queryctrl.name << endl;
2069 cerr <<
"Private Control " <<
queryctrl.name << endl;
2070#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2071 if ((
queryctrl.type == V4L2_CTRL_TYPE_MENU) || (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2073 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2076 if (
queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2077 cerr <<
" boolean" << endl;
2078 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2079 cerr <<
" integer" << endl;
2082 if (
queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2083 cerr <<
" button" << endl;
2087 if (
errno == EINVAL)
2098#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2099 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2100 cerr <<
" Menu items:" << endl;
2101 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2102 cerr <<
" Integer Menu items:" << endl;
2104 cerr <<
" Menu items:" << endl;
2114 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2116#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2117 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2120 menuname[18] =
'\0';
2121 snprintf(menuname, 19,
"0x%016" PRIX64,
static_cast<int64_t
>(
querymenu.value));
2122 cerr <<
" " << menuname << endl;
2135 double &ctrl_value,
char * errmsg)
2137 struct v4l2_control control;
2143 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &
queryctrl))
2145 if (
errno != EINVAL)
2146 return errno_exit(
"VIDIOC_QUERYCTRL", errmsg);
2150 cerr <<
"#" << ctrl_id <<
" is not supported" << endl;
2151 snprintf(errmsg,
ERRMSGSIZ,
"# %d is not supported", ctrl_id);
2155 else if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2157 cerr <<
"#" << ctrl_id <<
" is disabled" << endl;
2158 snprintf(errmsg,
ERRMSGSIZ,
"# %d is disabled", ctrl_id);
2169 control.id = ctrl_id;
2171 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2172 ctrl_value = control.value;
2174 cerr <<
queryctrl.name <<
" -- min: " << ctrl_min <<
" max: " << ctrl_max <<
" step: " << ctrl_step
2175 <<
" value: " << ctrl_value << endl;
2181 unsigned int * noptions,
const char * dev,
const char * group)
2183 struct v4l2_control control;
2186 unsigned int * num_ctrls =
nullptr;
2189 unsigned int nopt = 0;
2190 char optname[] =
"OPT000";
2191 char swonname[] =
"SET_OPT000";
2192 char swoffname[] =
"UNSET_OPT000";
2193 char menuname[] =
"MENU000";
2194 char menuoptname[] =
"MENU000_OPT000";
2204 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2206 cerr <<
queryctrl.name <<
" is disabled." << endl;
2210 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2212 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2215 num_ctrls = (num_ctrls ==
nullptr) ?
2216 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2217 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2225 numbers[nnum].value =
queryctrl.default_value;
2230 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2231 numbers[nnum].value = control.value;
2237 <<
" step: " <<
queryctrl.step <<
" value: " << numbers[nnum].value << endl;
2241 if (
queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2244 snprintf(optname + 3, 4,
"%03d", nopt);
2245 snprintf(swonname + 7, 4,
"%03d", nopt);
2246 snprintf(swoffname + 9, 4,
"%03d", nopt);
2248 opt = (opt ==
nullptr) ?
2254 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2261 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2262 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2268#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2269 if ((
queryctrl.type == V4L2_CTRL_TYPE_MENU) || (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2271 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2275 unsigned int nmenuopt = 0;
2277 snprintf(menuname + 4, 4,
"%03d", nopt);
2278 snprintf(menuoptname + 4, 4,
"%03d", nopt);
2279 menuoptname[7] =
'_';
2281 opt = (opt ==
nullptr) ?
2287 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2298 snprintf(menuoptname + 11, 4,
"%03d", nmenuopt);
2299#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2300 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2305 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2307 snprintf(sname, 19,
"0x%016" PRIX64,
static_cast<int64_t
>(
querymenu.value));
2315 (
int)
sizeof(sname), sname, (
int)
sizeof(menuoptname), menuoptname, nmenuopt);
2332 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2333 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2342 if (
errno != EINVAL)
2348 perror(
"VIDIOC_QUERYCTRL");
2358 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2360 cerr <<
queryctrl.name <<
" is disabled." << endl;
2364 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2366 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2369 num_ctrls = (num_ctrls ==
nullptr) ?
2370 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2371 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2379 numbers[nnum].value =
queryctrl.default_value;
2384 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2385 numbers[nnum].value = control.value;
2391 <<
" value: " << numbers[nnum].value << endl;
2395 if (
queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2398 snprintf(optname + 3, 4,
"%03d", nopt);
2399 snprintf(swonname + 7, 4,
"%03d", nopt);
2400 snprintf(swoffname + 9, 4,
"%03d", nopt);
2402 opt = (opt ==
nullptr) ?
2408 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2416 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2417 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2424 if ((
queryctrl.type == V4L2_CTRL_TYPE_MENU) || (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2426 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2430 unsigned int nmenuopt = 0;
2432 snprintf(menuname + 4, 4,
"%03d", nopt);
2433 snprintf(menuoptname + 4, 4,
"%03d", nopt);
2434 menuoptname[7] =
'_';
2436 opt = (opt ==
nullptr) ?
2442 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2453 snprintf(menuoptname + 11, 4,
"%03d", nmenuopt);
2454#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2455 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2460 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2462 snprintf(sname, 19,
"0x%016" PRIX64,
static_cast<int64_t
>(
querymenu.value));
2470 (
int)
sizeof(sname), sname, (
int)
sizeof(menuoptname), menuoptname, nmenuopt);
2488 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2489 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2501 for (
int i = 0; i < nnum; i++)
2502 numbers[i].aux0 = &num_ctrls[i];
2514 struct v4l2_control control;
2518 unsigned int * num_ctrls =
nullptr;
2525 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2527 cerr <<
queryctrl.name <<
" is disabled." << endl;
2531 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2533 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2536 num_ctrls = (num_ctrls ==
nullptr) ?
2537 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2538 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2546 numbers[nnum].value =
queryctrl.default_value;
2551 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2552 numbers[nnum].value = control.value;
2564 else if (
errno != EINVAL)
2568 return errno_exit(
"VIDIOC_QUERYCTRL", errmsg);
2576 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2578 cerr <<
queryctrl.name <<
" is disabled." << endl;
2582 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2584 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2587 num_ctrls = (num_ctrls ==
nullptr) ?
2588 (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2589 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2597 numbers[nnum].value =
queryctrl.default_value;
2602 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2603 numbers[nnum].value = control.value;
2616 for (
int i = 0; i < nnum; i++)
2617 numbers[i].aux0 = &num_ctrls[i];
2627 struct v4l2_control control;
2630 control.id = ctrl_id;
2632 if (-1 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2634 *value = (double)control.value;
2640 struct v4l2_control control;
2645 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &
queryctrl))
2647 if ((
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) || (
queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) ||
2648 (
queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE) || (
queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE))
2652 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY ?
"read only " :
"",
2653 queryctrl.flags & V4L2_CTRL_FLAG_GRABBED ?
"grabbed " :
"",
2654 queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE ?
"inactive " :
"",
2655 queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE ?
"volatile" :
"");
2663 control.id = ctrl_id;
2664 control.value = (int)new_value;
2665 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CTRL, &control))
2676 struct v4l2_control control;
2681 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &
queryctrl))
2683 if ((
queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) || (
queryctrl.flags & V4L2_CTRL_FLAG_GRABBED) ||
2684 (
queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE) || (
queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE))
2688 queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY ?
"read only " :
"",
2689 queryctrl.flags & V4L2_CTRL_FLAG_GRABBED ?
"grabbed " :
"",
2690 queryctrl.flags & V4L2_CTRL_FLAG_INACTIVE ?
"inactive " :
"",
2691 queryctrl.flags & V4L2_CTRL_FLAG_VOLATILE ?
"volatile" :
"");
2699 control.id = ctrl_id;
2700 control.value = new_value;
2701 if (-1 ==
XIOCTL(
fd, VIDIOC_S_CTRL, &control))
2716 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2717 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &
queryctrl))
2720 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2723 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2725 cerr <<
"DISABLED--Control " <<
queryctrl.name << endl;
2726 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2730 if (
queryctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
2732 cerr <<
"Control Class " <<
queryctrl.name << endl;
2733 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2737 cerr <<
"Control " <<
queryctrl.name << endl;
2739#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2740 if ((
queryctrl.type == V4L2_CTRL_TYPE_MENU) || (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2742 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2745 if (
queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2746 cerr <<
" boolean" << endl;
2747 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2748 cerr <<
" integer" << endl;
2751 if (
queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2752 cerr <<
" button" << endl;
2753 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2761 unsigned int * noptions,
const char * dev,
const char * group)
2763 struct v4l2_control control;
2766 unsigned int * num_ctrls =
nullptr;
2769 unsigned int nopt = 0;
2770 char optname[] =
"OPT000";
2771 char swonname[] =
"SET_OPT000";
2772 char swoffname[] =
"UNSET_OPT000";
2773 char menuname[] =
"MENU000";
2774 char menuoptname[] =
"MENU000_OPT000";
2780 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2781 if (-1 == ioctl(
fd, VIDIOC_QUERYCTRL, &
queryctrl))
2785 queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
2788 if (
queryctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS)
2792 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2796 if (
queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
2800 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2804 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
2806 numbers = (numbers ==
nullptr) ? (
INumber *)malloc(
sizeof(
INumber)) :
2809 num_ctrls = (num_ctrls ==
nullptr) ? (
unsigned int *)malloc(
sizeof(
unsigned int)) :
2810 (
unsigned int *)realloc(num_ctrls, (nnum + 1) *
sizeof(
unsigned int));
2818 numbers[nnum].value =
queryctrl.default_value;
2823 if (0 ==
XIOCTL(
fd, VIDIOC_G_CTRL, &control))
2824 numbers[nnum].value = control.value;
2835 if (
queryctrl.type == V4L2_CTRL_TYPE_BOOLEAN)
2838 snprintf(optname + 3, 4,
"%03d", nopt);
2839 snprintf(swonname + 7, 4,
"%03d", nopt);
2840 snprintf(swoffname + 9, 4,
"%03d", nopt);
2847 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2852 (sw + 1)->aux =
nullptr;
2856 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2857 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2860 queryctrl.name, (control.value ?
"On" :
"Off"));
2863 if (
queryctrl.type == V4L2_CTRL_TYPE_BUTTON)
2866 snprintf(optname + 3, 4,
"%03d", nopt);
2867 snprintf(swonname + 7, 4,
"%03d", nopt);
2878 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2879 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2884#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2885 if ((
queryctrl.type == V4L2_CTRL_TYPE_MENU) || (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU))
2887 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2891 unsigned int nmenuopt = 0;
2893 snprintf(menuname + 4, 4,
"%03d", nopt);
2894 snprintf(menuoptname + 4, 4,
"%03d", nopt);
2895 menuoptname[7] =
'_';
2902 XIOCTL(
fd, VIDIOC_G_CTRL, &control);
2913 snprintf(menuoptname + 11, 4,
"%03d", nmenuopt);
2914#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
2915 if (
queryctrl.type == V4L2_CTRL_TYPE_MENU)
2920 if (
queryctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU)
2922 snprintf(sname, 19,
"0x%016" PRIX64,
static_cast<int64_t
>(
querymenu.value));
2930 (
int)
sizeof(sname), sname, (
int)
sizeof(menuoptname), menuoptname, nmenuopt,
2935 sw[nmenuopt].aux = malloc(
sizeof(
unsigned int));
2936 *(
unsigned int *)(sw[nmenuopt].aux) = (
querymenu.index);
2949 opt[nopt].
aux = malloc(
sizeof(
unsigned int));
2950 *(
unsigned int *)(opt[nopt].aux) = (
queryctrl.id);
2962 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
2966 for (
int i = 0; i < nnum; i++)
2967 numbers[i].aux0 = &num_ctrls[i];
2994 std::map<std::string, std::string> devices;
2996 auto searchPath = [&](std::string prefix)
2998 struct dirent **namelist;
2999 std::vector<std::string> detectedDevices;
3004 for (
int i = devCount - 1; i >= 0; i--)
3006 std::string s(namelist[i]->d_name);
3007 s.erase(s.find_last_not_of(
" \n\r\t") + 1);
3008 detectedDevices.push_back(prefix + s);
3012 return detectedDevices;
3015 const std::vector<std::string> videoDevices = searchPath(
"/dev/");
3017 for (
const auto &oneDevice : videoDevices)
3019 int fd = open(oneDevice.c_str(), O_RDWR | O_NONBLOCK, 0);
3022 struct v4l2_capability
cap;
3023 if (ioctl(
fd, VIDIOC_QUERYCAP, &
cap) >= 0)
3025 devices[std::string(
reinterpret_cast<const char *
>(
cap.card))] = oneDevice;
3039 static const char *filter_names[] = {
"video",
nullptr };
3040 const char **filter;
3042 for (filter = filter_names; *filter; ++filter)
3044 if (strstr(entry->d_name, *filter) !=
nullptr)
void init_read(unsigned int buffer_size)
struct v4l2_querymenu querymenu
int read_frame(char *errsg)
char deviceName[MAXINDIDEVICE]
int stop_capturing(char *errmsg)
int check_device(char *errmsg)
int xioctl(int fd, int request, void *arg, char const *const request_str)
virtual void disconnectCam(bool stopcapture)
struct v4l2_queryctrl queryctrl
int(V4L2_Base::* setframerate)(struct v4l2_fract frate, char *errmsg)
int pwcsetframerate(struct v4l2_fract frate, char *errmsg)
static int video_dev_file_select(const dirent *entry)
bool enumerate_ext_ctrl()
int stdsetframerate(struct v4l2_fract frate, char *errmsg)
int open_device(const char *devpath, char *errmsg)
int setINTControl(unsigned int ctrl_id, double new_value, char *errmsg)
struct v4l2_capability cap
int query_ctrl(unsigned int ctrl_id, double &ctrl_min, double &ctrl_max, double &ctrl_step, double &ctrl_value, char *errmsg)
void queryControls(INumberVectorProperty *nvp, unsigned int *nnumber, ISwitchVectorProperty **options, unsigned int *noptions, const char *dev, const char *group)
int getControl(unsigned int ctrl_id, double *value, char *errmsg)
int errno_exit(const char *s, char *errmsg)
void setColorProcessing(bool quantization, bool colorconvert, bool linearization)
void getframerates(ISwitchVectorProperty *frameratessp, INumberVectorProperty *frameratenp)
bool is_compressed() const
Helper indicating whether current pixel format is compressed or not.
void registerCallback(WPF *fp, void *ud)
V4L2_Decode * v4l2_decode
int uninit_device(char *errmsg)
void getcaptureformats(ISwitchVectorProperty *captureformatssp)
static void newFrame(int fd, void *p)
int start_capturing(char *errmsg)
struct v4l2_fract stdgetframerate()
void getcapturesizes(ISwitchVectorProperty *capturesizessp, INumberVectorProperty *capturesizenp)
unsigned char * getMJPEGBuffer(int &size)
void init_userp(unsigned int buffer_size)
struct v4l2_fract(V4L2_Base::* getframerate)()
void setDeviceName(const char *name)
int init_device(char *errmsg)
int setcapturesize(unsigned int w, unsigned int h, char *errmsg)
int setcaptureformat(unsigned int captureformatindex, char *errmsg)
struct v4l2_cropcap cropcap
int ioctl_set_format(struct v4l2_format new_fmt, char *errmsg)
static std::map< std::string, std::string > enumerate()
int enumeratedCaptureFormats
virtual void getMaxMinSize(int &x_max, int &y_max, int &x_min, int &y_min)
unsigned char * getRGBBuffer()
int setcroprect(int x, int y, int w, int h, char *errmsg)
bool queryExtControls(INumberVectorProperty *nvp, unsigned int *nnumber, ISwitchVectorProperty **options, unsigned int *noptions, const char *dev, const char *group)
struct v4l2_fract frameRate
int init_mmap(char *errmsg)
void getinputs(ISwitchVectorProperty *inputssp)
virtual int setSize(int x, int y)
int setinput(unsigned int inputindex, char *errmsg)
int setOPTControl(unsigned int ctrl_id, unsigned int new_value, char *errmsg)
int queryINTControls(INumberVectorProperty *nvp)
virtual int connectCam(const char *devpath, char *errmsg, int pixelFormat=-1, int width=-1, int height=-1)
V4L2_Decoder * getDefaultDecoder()
virtual unsigned char * getRGBBuffer()=0
virtual void setQuantization(bool)=0
virtual void resetcrop()=0
virtual void decode(unsigned char *frame, struct v4l2_buffer *buf, bool native)=0
virtual void setformat(struct v4l2_format f, bool use_ext_pix_format)=0
virtual void setLinearization(bool)=0
virtual float * getLinearY()=0
virtual unsigned char * getMJPEGBuffer(int &size)=0
virtual unsigned char * getU()=0
virtual bool issupportedformat(unsigned int format)=0
virtual bool setcrop(struct v4l2_crop c)=0
virtual unsigned char * getY()=0
virtual unsigned char * getV()=0
virtual void usesoftcrop(bool c)=0
virtual const std::vector< unsigned int > & getsupportedformats()=0
virtual const char * getName()
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.
Number vector property descriptor.
Switch vector property descriptor.
#define XIOCTL(fd, ioctl, arg)