36 #include <sys/ioctl.h>
37 #include <linux/videodev2.h>
46 #define CLEAR(x) memset(&(x), 0, sizeof (x))
60 struct v4l2_buffer buf;
66 FD_SET(
dev->fd, &fds);
73 int sr = select(
dev->fd + 1, &fds, NULL, NULL, &tv);
78 if (EINTR == errno) {
continue; }
79 printf(
"[v4l2-capture] Select error %d on %s: %s\n", errno,
dev->name, strerror(errno));
80 dev->thread = (pthread_t) NULL;
83 printf(
"[v4l2-capture] Select timeout on %s\n",
dev->name);
91 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
92 buf.memory = V4L2_MEMORY_MMAP;
93 if (ioctl(
dev->fd, VIDIOC_DQBUF, &buf) < 0) {
94 printf(
"[v4l2-capture] Dequeue of buffer failed for %s.\n",
dev->name);
95 dev->thread = (pthread_t) NULL;
98 assert(buf.index <
dev->buffers_cnt);
101 dev->buffers[buf.index].timestamp = buf.timestamp;
102 dev->buffers[buf.index].pprz_timestamp = now_ts;
106 pthread_mutex_lock(&
dev->mutex);
108 dev->buffers_deq_idx = buf.index;
109 pthread_mutex_unlock(&
dev->mutex);
115 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
116 buf.memory = V4L2_MEMORY_MMAP;
117 buf.index = prev_idx;
118 if (ioctl(
dev->fd, VIDIOC_QBUF, &buf) < 0) {
119 printf(
"[v4l2-capture] Could not enqueue %d for %s\n", prev_idx,
dev->name);
139 struct v4l2_subdev_format sfmt;
143 int fd = open(subdev_name, O_RDWR, 0);
145 printf(
"[v4l2] Cannot open subdevice '%s': %d, %s\n", subdev_name, errno, strerror(errno));
150 if (ioctl(
fd, VIDIOC_SUBDEV_G_FMT, &sfmt) < 0) {
151 printf(
"[v4l2] Could not get subdevice data format settings of %s\n", subdev_name);
158 sfmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
159 sfmt.format.width = size.
w;
160 sfmt.format.height = size.
h;
161 sfmt.format.code = code;
162 sfmt.format.field = V4L2_FIELD_NONE;
163 sfmt.format.colorspace = 1;
165 if (ioctl(
fd, VIDIOC_SUBDEV_S_FMT, &sfmt) < 0) {
166 printf(
"[v4l2] Could not set subdevice data format settings of %s\n", subdev_name);
188 struct v4l2_capability cap;
189 struct v4l2_format fmt;
190 struct v4l2_requestbuffers req;
191 struct v4l2_fmtdesc fmtdesc;
192 struct v4l2_crop crp;
201 int fd = open(device_name, O_RDWR | O_NONBLOCK, 0);
203 printf(
"[v4l2] Cannot open '%s': %d, %s\n", device_name, errno, strerror(errno));
208 if (ioctl(
fd, VIDIOC_QUERYCAP, &cap) < 0) {
209 printf(
"[v4l2] %s is no V4L2 device\n", device_name);
215 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
216 printf(
"[v4l2] %s is no V4L2 video capturing device\n", device_name);
221 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
222 printf(
"[v4l2] %s isn't capable of streaming (TODO: support reading)\n", device_name);
227 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
228 while (ioctl(
fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
230 if(fmtdesc.pixelformat == _pixelformat)
235 if(fmtdesc.index != 0 && fmtdesc.pixelformat != _pixelformat) {
236 printf(
"[v4l2] Pixelformat not available on device %s (wanted: %4X)\r\n", device_name, _pixelformat);
241 crp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
244 crp.c.width = crop.
w;
245 crp.c.height = crop.
h;
248 if(crop.
x != 0 || crop.
y != 0 || crop.
w !=
size.w || crop.
h !=
size.h) {
249 if (ioctl(
fd, VIDIOC_S_CROP, &crp) < 0) {
250 printf(
"[v4l2] Could not set crop window of %s\n", device_name);
257 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
258 fmt.fmt.pix.width =
size.w;
259 fmt.fmt.pix.height =
size.h;
260 fmt.fmt.pix.pixelformat = _pixelformat;
261 fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
262 fmt.fmt.pix.field = V4L2_FIELD_NONE;
264 if (ioctl(
fd, VIDIOC_S_FMT, &fmt) < 0) {
265 printf(
"[v4l2] Could not set data format settings of %s\n", device_name);
271 req.count = buffers_cnt;
272 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
273 req.memory = V4L2_MEMORY_MMAP;
274 if (ioctl(
fd, VIDIOC_REQBUFS, &req) < 0) {
275 printf(
"[v4l2] %s Does not support memory mapping\n", device_name);
283 printf(
"[v4l2] Not enough memory for %s to initialize %d MMAP buffers\n", device_name, req.count);
289 for (i = 0; i < req.count; ++i) {
290 struct v4l2_buffer buf;
294 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
295 buf.memory = V4L2_MEMORY_MMAP;
297 if (ioctl(
fd, VIDIOC_QUERYBUF, &buf) < 0) {
298 printf(
"[v4l2] Querying buffer %d from %s failed\n", i, device_name);
305 buffers[i].length = buf.length;
306 buffers[i].buf = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, buf.m.offset);
307 if (MAP_FAILED ==
buffers[i].buf) {
308 printf(
"[v4l2] Mapping buffer %d with length %d from %s failed\n", i, buf.length, device_name);
315 printf(
"[v4l2] Physical memory %d is not contiguous with length %d from %s\n", i, buf.length, device_name);
327 dev->name = strdup(device_name);
331 dev->buffers_cnt = req.count;
352 pthread_mutex_lock(&
dev->mutex);
356 img_idx =
dev->buffers_deq_idx;
360 pthread_mutex_unlock(&
dev->mutex);
370 img->
buf =
dev->buffers[img_idx].buf;
371 img->
ts =
dev->buffers[img_idx].timestamp;
372 img->
pprz_ts =
dev->buffers[img_idx].pprz_timestamp;
388 pthread_mutex_lock(&
dev->mutex);
390 img_idx =
dev->buffers_deq_idx;
393 pthread_mutex_unlock(&
dev->mutex);
406 img->
buf =
dev->buffers[img_idx].buf;
407 img->
ts =
dev->buffers[img_idx].timestamp;
408 img->
pprz_ts =
dev->buffers[img_idx].pprz_timestamp;
420 struct v4l2_buffer buf;
424 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
425 buf.memory = V4L2_MEMORY_MMAP;
427 if (ioctl(
dev->fd, VIDIOC_QBUF, &buf) < 0) {
428 printf(
"[v4l2] Could not enqueue %d for %s\n", img->
buf_idx,
dev->name);
442 enum v4l2_buf_type
type;
445 if (
dev->thread != (pthread_t)NULL) {
446 printf(
"[v4l2] There is already a capturing thread running for %s\n",
dev->name);
452 for (i = 0; i <
dev->buffers_cnt; ++i) {
453 struct v4l2_buffer buf;
456 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
457 buf.memory = V4L2_MEMORY_MMAP;
459 if (ioctl(
dev->fd, VIDIOC_QBUF, &buf) < 0) {
460 printf(
"[v4l2] Could not enqueue buffer %d during start capture for %s\n", i,
dev->name);
466 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
467 if (ioctl(
dev->fd, VIDIOC_STREAMON, &
type) < 0) {
468 printf(
"[v4l2] Could not start stream of %s, %d %s\n",
dev->name, errno, strerror(errno));
475 printf(
"[v4l2] Could not start capturing thread for %s (return code: %d)\n",
dev->name, rc);
478 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
479 if (ioctl(
dev->fd, VIDIOC_STREAMOFF, &
type) < 0) {
480 printf(
"[v4l2] Could not stop stream of %s\n",
dev->name);
484 dev->thread = (pthread_t) NULL;
489 pthread_setname_np(
dev->thread,
"v4l2");
504 enum v4l2_buf_type
type;
507 if (
dev->thread == (pthread_t) NULL) {
508 printf(
"[v4l2] Already stopped capture for %s\n",
dev->name);
513 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
514 if (ioctl(
dev->fd, VIDIOC_STREAMOFF, &
type) < 0) {
515 printf(
"[v4l2] Could not stop stream of %s\n",
dev->name);
520 if (pthread_cancel(
dev->thread) < 0) {
521 printf(
"[v4l2] Could not cancel thread for %s\n",
dev->name);
526 pthread_join(
dev->thread, NULL);
527 dev->thread = (pthread_t) NULL;
545 for (i = 0; i <
dev->buffers_cnt; ++i) {
546 if (munmap(
dev->buffers[i].buf,
dev->buffers[i].length) < 0) {
547 printf(
"[v4l2] Could not unmap buffer %d for %s\n", i,
dev->name);