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;
106 pthread_mutex_lock(&dev->
mutex);
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);
282 if (buffers == NULL) {
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);
314 if(
check_contiguity((
unsigned long)buffers[i].buf, getpid(), &pmem, buf.length)) {
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);
352 pthread_mutex_lock(&dev->
mutex);
360 pthread_mutex_unlock(&dev->
mutex);
388 pthread_mutex_lock(&dev->
mutex);
393 pthread_mutex_unlock(&dev->
mutex);
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);
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;
547 printf(
"[v4l2] Could not unmap buffer %d for %s\n", i, dev->
name);
#define V4L2_IMG_NONE
There currently no image available.
pthread_mutex_t mutex
Mutex lock for enqueue/dequeue of buffers (change the deq_idx)
uint32_t buf_size
The buffer size.
uint16_t h
height of the cropped area
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...
uint32_t physp
Physical address pointer.
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...
Capture images from a V4L2 device (Video for Linux 2)
int check_contiguity(unsigned long vaddr, pid_t pid, struct physmem *pmem, size_t size)
uint16_t y
Start position y (vertical)
uint16_t x
Start position x (horizontal)
uint32_t pprz_ts
The timestamp in us since system startup.
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 ...
struct v4l2_device * v4l2_init(char *device_name, struct img_size_t size, struct crop_t crop, uint8_t buffers_cnt, uint32_t _pixelformat)
Initialize a V4L2(Video for Linux 2) device.
bool v4l2_stop_capture(struct v4l2_device *dev)
Stop capturing of the image stream (Thread safe) This function is blocking until capturing thread is ...
uint16_t w
Width of the cropped area.
uint8_t buf_idx
Buffer index for V4L2 freeing.
uint32_t pprz_timestamp
The time of the image in us since system startup.
Architecture independent timing functions.
uint16_t h
The height of the image.
struct timeval timestamp
The time value of the image.
struct v4l2_img_buf * buffers
The memory mapped image buffers.
void * buf
Image buffer (depending on the image_type)
size_t length
The size of the buffer.
bool 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...
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...
static const struct usb_device_descriptor dev
void * buf
Pointer to the memory mapped buffer.
static struct adc_buf * buffers[NB_ADC *2]
First NB_ADC for bank 0, others for bank 2.
char * name
The name of the device.
struct timeval ts
The timestamp of creation.
bool v4l2_init_subdev(char *subdev_name, uint8_t pad, uint16_t code, struct img_size_t size)
Initialize a V4L2 subdevice.
bool v4l2_start_capture(struct v4l2_device *dev)
Start capturing images in streaming mode (Thread safe)
UYVY format (uint16 per pixel)
uint8_t buffers_cnt
The number of image buffers.
volatile uint8_t buffers_deq_idx
The current dequeued index.
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
pthread_t thread
The thread that handles the images.
uint16_t w
The width of the image.
enum image_type type
The image type.
int fd
The file pointer to the device.