Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
v4l2.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Freek van Tienen <freek.v.tienen@gmail.com>
3  * Copyright (C) 2011 Hugo Perquin - http://blog.perquin.com
4  *
5  * This file is part of Paparazzi.
6  *
7  * Paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * Paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, see
19  * <http://www.gnu.org/licenses/>.
20  *
21  */
22 
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <malloc.h>
35 #include <sys/mman.h>
36 #include <sys/ioctl.h>
37 #include <linux/videodev2.h>
38 #include <pthread.h>
39 
40 #include "v4l2.h"
41 
42 #define CLEAR(x) memset(&(x), 0, sizeof (x))
43 static void *v4l2_capture_thread(void *data);
44 
53 static void *v4l2_capture_thread(void *data)
54 {
55  struct v4l2_device *dev = (struct v4l2_device *)data;
56  struct v4l2_buffer buf;
57  struct timeval tv;
58  fd_set fds;
59 
60  while (TRUE) {
61  FD_ZERO(&fds);
62  FD_SET(dev->fd, &fds);
63 
64  // Set the timeout to 2 seconds
65  tv.tv_sec = 2;
66  tv.tv_usec = 0;
67 
68  // Wait until an image was taken, with a timeout of tv
69  int sr = select(dev->fd + 1, &fds, NULL, NULL, &tv);
70  if (sr < 0) {
71  // Was interrupted by a signal
72  if (EINTR == errno) { continue; }
73  printf("[v4l2-capture] Select error %d on %s: %s\n", errno, dev->name, strerror(errno));
74  dev->thread = (pthread_t) NULL;
75  return (void *) - 1;
76  } else if (sr == 0) {
77  printf("[v4l2-capture] Select timeout on %s\n", dev->name);
78  //continue;
79  dev->thread = (pthread_t) NULL;
80  return (void *) - 2;
81  }
82 
83  // Dequeue a buffer
84  CLEAR(buf);
85  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
86  buf.memory = V4L2_MEMORY_MMAP;
87  if (ioctl(dev->fd, VIDIOC_DQBUF, &buf) < 0) {
88  printf("[v4l2-capture] Dequeue of buffer failed for %s.\n", dev->name);
89  dev->thread = (pthread_t) NULL;
90  return (void *) - 3;
91  }
92  assert(buf.index < dev->buffers_cnt);
93 
94  // Copy the timestamp
95  memcpy(&dev->buffers[buf.index].timestamp, &buf.timestamp, sizeof(struct timeval));
96 
97  // Update the dequeued id
98  // We need lock because between setting prev_idx and updating the deq_idx the deq_idx could change
99  pthread_mutex_lock(&dev->mutex);
100  uint16_t prev_idx = dev->buffers_deq_idx;
101  dev->buffers_deq_idx = buf.index;
102  pthread_mutex_unlock(&dev->mutex);
103 
104  // Enqueue the previous image if not empty
105  if (prev_idx != V4L2_IMG_NONE) {
106  // Enqueue the previous buffer
107  CLEAR(buf);
108  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
109  buf.memory = V4L2_MEMORY_MMAP;
110  buf.index = prev_idx;
111  if (ioctl(dev->fd, VIDIOC_QBUF, &buf) < 0) {
112  printf("[v4l2-capture] Could not enqueue %d for %s\n", prev_idx, dev->name);
113  }
114  }
115 
116  }
117  return (void *)0;
118 }
119 
130 bool_t v4l2_init_subdev(char *subdev_name, uint8_t pad, uint8_t which, uint16_t code, uint16_t width, uint16_t height)
131 {
132  struct v4l2_subdev_format sfmt;
133  CLEAR(sfmt);
134 
135  // Try to open the subdevice
136  int fd = open(subdev_name, O_RDWR, 0);
137  if (fd < 0) {
138  printf("[v4l2] Cannot open subdevice '%s': %d, %s\n", subdev_name, errno, strerror(errno));
139  return FALSE;
140  }
141 
142  // Try to get the subdevice data format settings
143  if (ioctl(fd, VIDIOC_SUBDEV_G_FMT, &sfmt) < 0) {
144  printf("[v4l2] Could not get subdevice data format settings of %s\n", subdev_name);
145  close(fd);
146  return FALSE;
147  }
148 
149  // Set the new settings
150  sfmt.pad = pad;
151  sfmt.which = which;
152  sfmt.format.width = width;
153  sfmt.format.height = height;
154  sfmt.format.code = code;
155  sfmt.format.field = V4L2_FIELD_NONE;
156  sfmt.format.colorspace = 1;
157 
158  if (ioctl(fd, VIDIOC_SUBDEV_S_FMT, &sfmt) < 0) {
159  printf("[v4l2] Could not set subdevice data format settings of %s\n", subdev_name);
160  close(fd);
161  return FALSE;
162  }
163 
164  // Close the device
165  close(fd);
166  return TRUE;
167 }
168 
177 struct v4l2_device *v4l2_init(char *device_name, uint16_t width, uint16_t height, uint8_t buffers_cnt,
178  uint32_t _pixelformat)
179 {
180  uint8_t i;
181  struct v4l2_capability cap;
182  struct v4l2_format fmt;
183  struct v4l2_requestbuffers req;
184  CLEAR(cap);
185  CLEAR(fmt);
186  CLEAR(req);
187 
188  // Try to open the device
189  int fd = open(device_name, O_RDWR | O_NONBLOCK, 0);
190  if (fd < 0) {
191  printf("[v4l2] Cannot open '%s': %d, %s\n", device_name, errno, strerror(errno));
192  return NULL;
193  }
194 
195  // Try to fetch the capabilities of the V4L2 device
196  if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
197  printf("[v4l2] %s is no V4L2 device\n", device_name);
198  close(fd);
199  return NULL;
200  }
201 
202  // Check if the device is capable of capturing and streaming
203  if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
204  printf("[v4l2] %s is no V4L2 video capturing device\n", device_name);
205  close(fd);
206  return NULL;
207  }
208  if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
209  printf("[v4l2] %s isn't capable of streaming (TODO: support reading)\n", device_name);
210  close(fd);
211  return NULL;
212  }
213 
214  // TODO: Read video cropping and scaling information VIDIOC_CROPCAP
215 
216  // Set the format settings
217  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
218  fmt.fmt.pix.width = width;
219  fmt.fmt.pix.height = height;
220  fmt.fmt.pix.pixelformat = _pixelformat;
221  fmt.fmt.pix.field = V4L2_FIELD_NONE;
222 
223  if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
224  printf("[v4l2] Could not set data format settings of %s\n", device_name);
225  close(fd);
226  return NULL;
227  }
228 
229  // Request MMAP buffers
230  req.count = buffers_cnt;
231  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
232  req.memory = V4L2_MEMORY_MMAP;
233  if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
234  printf("[v4l2] %s Does not support memory mapping\n", device_name);
235  close(fd);
236  return NULL;
237  }
238 
239  // Allocate memory for the memory mapped buffers
240  struct v4l2_img_buf *buffers = calloc(req.count, sizeof(struct v4l2_img_buf));
241  if (buffers == NULL) {
242  printf("[v4l2] Not enough memory for %s to initialize %d MMAP buffers\n", device_name, req.count);
243  close(fd);
244  return NULL;
245  }
246 
247  // Go trough the buffers and initialize them
248  for (i = 0; i < req.count; ++i) {
249  struct v4l2_buffer buf;
250  CLEAR(buf);
251 
252  // Request the buffer information
253  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
254  buf.memory = V4L2_MEMORY_MMAP;
255  buf.index = i;
256  if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
257  printf("[v4l2] Querying buffer %d from %s failed\n", i, device_name);
258  free(buffers);
259  close(fd);
260  return NULL;
261  }
262 
263  // Map the buffer
264  buffers[i].length = buf.length;
265  buffers[i].buf = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
266  if (MAP_FAILED == buffers[i].buf) {
267  printf("[v4l2] Mapping buffer %d with length %d from %s failed\n", i, buf.length, device_name);
268  free(buffers);
269  close(fd);
270  return NULL;
271  }
272  }
273 
274  // Create the device only when everything succeeded
275  struct v4l2_device *dev = (struct v4l2_device *)malloc(sizeof(struct v4l2_device));
276  CLEAR(*dev);
277  dev->name = strdup(device_name); // NOTE: needs to be freed
278  dev->fd = fd;
279  dev->w = width;
280  dev->h = height;
281  dev->buffers_cnt = req.count;
282  dev->buffers = buffers;
283  return dev;
284 }
285 
294 void v4l2_image_get(struct v4l2_device *dev, struct image_t *img)
295 {
296  uint16_t img_idx = V4L2_IMG_NONE;
297 
298  // Continu to wait for an image
299  while (img_idx == V4L2_IMG_NONE) {
300  // We first check if the deq_idx is ok, this reduces the amount of locks
301  if (dev->buffers_deq_idx != V4L2_IMG_NONE) {
302  pthread_mutex_lock(&dev->mutex);
303 
304  // We need to check it here again, because it could be changed
305  if (dev->buffers_deq_idx != V4L2_IMG_NONE) {
306  img_idx = dev->buffers_deq_idx;
308  }
309 
310  pthread_mutex_unlock(&dev->mutex);
311  }
312  }
313 
314  // Set the image
315  img->type = IMAGE_YUV422;
316  img->w = dev->w;
317  img->h = dev->h;
318  img->buf_idx = img_idx;
319  img->buf_size = dev->buffers[img_idx].length;
320  img->buf = dev->buffers[img_idx].buf;
321  memcpy(&img->ts, &dev->buffers[img_idx].timestamp, sizeof(struct timeval));
322 }
323 
332 bool_t v4l2_image_get_nonblock(struct v4l2_device *dev, struct image_t *img)
333 {
334  uint16_t img_idx = V4L2_IMG_NONE;
335 
336  // Try to get the current image
337  pthread_mutex_lock(&dev->mutex);
338  if (dev->buffers_deq_idx != V4L2_IMG_NONE) {
339  img_idx = dev->buffers_deq_idx;
341  }
342  pthread_mutex_unlock(&dev->mutex);
343 
344  // Check if we really got an image
345  if (img_idx == V4L2_IMG_NONE) {
346  return FALSE;
347  } else {
348  // Set the image
349  img->type = IMAGE_YUV422;
350  img->w = dev->w;
351  img->h = dev->h;
352  img->buf_idx = img_idx;
353  img->buf_size = dev->buffers[img_idx].length;
354  img->buf = dev->buffers[img_idx].buf;
355  memcpy(&img->ts, &dev->buffers[img_idx].timestamp, sizeof(struct timeval));
356  return TRUE;
357  }
358 }
359 
366 void v4l2_image_free(struct v4l2_device *dev, struct image_t *img)
367 {
368  struct v4l2_buffer buf;
369 
370  // Enqueue the buffer
371  CLEAR(buf);
372  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
373  buf.memory = V4L2_MEMORY_MMAP;
374  buf.index = img->buf_idx;
375  if (ioctl(dev->fd, VIDIOC_QBUF, &buf) < 0) {
376  printf("[v4l2] Could not enqueue %d for %s\n", img->buf_idx, dev->name);
377  }
378 }
379 
388 {
389  uint8_t i;
390  enum v4l2_buf_type type;
391 
392  // Check if not already running
393  if (dev->thread != (pthread_t)NULL) {
394  printf("[v4l2] There is already a capturing thread running for %s\n", dev->name);
395  return FALSE;
396  }
397 
398  // Enqueue all buffers
400  for (i = 0; i < dev->buffers_cnt; ++i) {
401  struct v4l2_buffer buf;
402 
403  CLEAR(buf);
404  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
405  buf.memory = V4L2_MEMORY_MMAP;
406  buf.index = i;
407  if (ioctl(dev->fd, VIDIOC_QBUF, &buf) < 0) {
408  printf("[v4l2] Could not enqueue buffer %d during start capture for %s\n", i, dev->name);
409  return FALSE;
410  }
411  }
412 
413  // Start the stream
414  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
415  if (ioctl(dev->fd, VIDIOC_STREAMON, &type) < 0) {
416  printf("[v4l2] Could not start stream of %s, %d %s\n", dev->name, errno, strerror(errno));
417  return FALSE;
418  }
419 
420  //Start the capturing thread
421  int rc = pthread_create(&dev->thread, NULL, v4l2_capture_thread, dev);
422  if (rc < 0) {
423  printf("[v4l2] Could not start capturing thread for %s (return code: %d)\n", dev->name, rc);
424 
425  // Stop the stream
426  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
427  if (ioctl(dev->fd, VIDIOC_STREAMOFF, &type) < 0) {
428  printf("[v4l2] Could not stop stream of %s\n", dev->name);
429  }
430 
431  // Reset the thread
432  dev->thread = (pthread_t) NULL;
433  return FALSE;
434  }
435 
436  return TRUE;
437 }
438 
447 {
448  enum v4l2_buf_type type;
449 
450  // First check if still running
451  if (dev->thread == (pthread_t) NULL) {
452  printf("[v4l2] Already stopped capture for %s\n", dev->name);
453  return FALSE;
454  }
455 
456  // Stop the stream
457  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
458  if (ioctl(dev->fd, VIDIOC_STREAMOFF, &type) < 0) {
459  printf("[v4l2] Could not stop stream of %s\n", dev->name);
460  return FALSE;
461  }
462 
463  // Stop the thread
464  if (pthread_cancel(dev->thread) < 0) {
465  printf("[v4l2] Could not cancel thread for %s\n", dev->name);
466  return FALSE;
467  }
468 
469  // Wait for the thread to be finished
470  pthread_join(dev->thread, NULL);
471  dev->thread = (pthread_t) NULL;
472  return TRUE;
473 }
474 
482 {
483  uint8_t i;
484 
485  // Stop capturing (ignore result as it may already be stopped)
486  v4l2_stop_capture(dev);
487 
488  // Unmap all buffers
489  for (i = 0; i < dev->buffers_cnt; ++i) {
490  if (munmap(dev->buffers[i].buf, dev->buffers[i].length) < 0) {
491  printf("[v4l2] Could not unmap buffer %d for %s\n", i, dev->name);
492  }
493  }
494 
495  // Close the file pointer and free all memory
496  close(dev->fd);
497  free(dev->name);
498  free(dev);
499 }
unsigned short uint16_t
Definition: types.h:16
#define V4L2_IMG_NONE
There currently no image available.
Definition: v4l2.h:38
pthread_mutex_t mutex
Mutex lock for enqueue/dequeue of buffers (change the deq_idx)
Definition: v4l2.h:56
uint32_t buf_size
The buffer size.
Definition: image.h:49
bool_t v4l2_start_capture(struct v4l2_device *dev)
Start capturing images in streaming mode (Thread safe)
Definition: v4l2.c:387
void v4l2_image_free(struct v4l2_device *dev, struct image_t *img)
Free the image and enqueue the buffer (Thread safe) This must be done after processing the image...
Definition: v4l2.c:366
void v4l2_image_get(struct v4l2_device *dev, struct image_t *img)
Get the latest image buffer and lock it (Thread safe, BLOCKING) This functions blocks until image acc...
Definition: v4l2.c:294
Capture images from a V4L2 device (Video for Linux 2)
Definition: image.h:42
bool_t v4l2_stop_capture(struct v4l2_device *dev)
Stop capturing of the image stream (Thread safe) This function is blocking until capturing thread is ...
Definition: v4l2.c:446
void v4l2_close(struct v4l2_device *dev)
Close the V4L2 device (Thread safe) This needs to be preformed to clean up all the buffers and close ...
Definition: v4l2.c:481
#define FALSE
Definition: std.h:5
uint8_t buf_idx
Buffer index for V4L2 freeing.
Definition: image.h:48
#define TRUE
Definition: std.h:4
uint16_t h
The height of the image.
Definition: v4l2.h:53
struct timeval timestamp
The time value of the image.
Definition: v4l2.h:43
uint16_t w
Image width.
Definition: image.h:44
unsigned long uint32_t
Definition: types.h:18
uint16_t h
Image height.
Definition: image.h:45
struct v4l2_img_buf * buffers
The memory mapped image buffers.
Definition: v4l2.h:57
void * buf
Image buffer (depending on the image_type)
Definition: image.h:50
size_t length
The size of the buffer.
Definition: v4l2.h:42
static void * v4l2_capture_thread(void *data)
The main capturing thread This thread handles the queue and dequeue of buffers, to make sure only the...
Definition: v4l2.c:53
bool_t v4l2_init_subdev(char *subdev_name, uint8_t pad, uint8_t which, uint16_t code, uint16_t width, uint16_t height)
Initialize a V4L2 subdevice.
Definition: v4l2.c:130
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:69
void * buf
Pointer to the memory mapped buffer.
Definition: v4l2.h:44
static struct adc_buf * buffers[NB_ADC *2]
First NB_ADC for bank 0, others for bank 2.
Definition: adc_arch.c:51
char * name
The name of the device.
Definition: v4l2.h:49
unsigned char uint8_t
Definition: types.h:14
struct timeval ts
The timestamp of creation.
Definition: image.h:46
int fd
Definition: serial.c:26
UYVY format (uint16 per pixel)
Definition: image.h:35
uint8_t buffers_cnt
The number of image buffers.
Definition: v4l2.h:54
bool_t v4l2_image_get_nonblock(struct v4l2_device *dev, struct image_t *img)
Get the latest image and lock it (Thread safe, NON BLOCKING) This function returns NULL if it can't g...
Definition: v4l2.c:332
#define CLEAR(x)
Definition: v4l2.c:42
volatile uint8_t buffers_deq_idx
The current dequeued index.
Definition: v4l2.h:55
pthread_t thread
The thread that handles the images.
Definition: v4l2.h:51
struct v4l2_device * v4l2_init(char *device_name, uint16_t width, uint16_t height, uint8_t buffers_cnt, uint32_t _pixelformat)
Initialize a V4L2(Video for Linux 2) device.
Definition: v4l2.c:177
uint16_t w
The width of the image.
Definition: v4l2.h:52
enum image_type type
The image type.
Definition: image.h:43
int fd
The file pointer to the device.
Definition: v4l2.h:50