36 #include <sys/ioctl.h>
37 #include <linux/videodev2.h>
42 #define CLEAR(x) memset(&(x), 0, sizeof (x))
56 struct v4l2_buffer buf;
62 FD_SET(dev->
fd, &fds);
69 int sr = select(dev->
fd + 1, &fds, NULL, NULL, &tv);
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;
77 printf(
"[v4l2-capture] Select timeout on %s\n", dev->
name);
79 dev->
thread = (pthread_t) NULL;
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;
95 memcpy(&dev->
buffers[buf.index].
timestamp, &buf.timestamp,
sizeof(
struct timeval));
99 pthread_mutex_lock(&dev->
mutex);
102 pthread_mutex_unlock(&dev->
mutex);
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);
132 struct v4l2_subdev_format sfmt;
136 int fd = open(subdev_name, O_RDWR, 0);
138 printf(
"[v4l2] Cannot open subdevice '%s': %d, %s\n", subdev_name, errno, strerror(errno));
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);
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;
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);
181 struct v4l2_capability cap;
182 struct v4l2_format fmt;
183 struct v4l2_requestbuffers req;
189 int fd = open(device_name, O_RDWR | O_NONBLOCK, 0);
191 printf(
"[v4l2] Cannot open '%s': %d, %s\n", device_name, errno, strerror(errno));
196 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
197 printf(
"[v4l2] %s is no V4L2 device\n", device_name);
203 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
204 printf(
"[v4l2] %s is no V4L2 video capturing device\n", device_name);
208 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
209 printf(
"[v4l2] %s isn't capable of streaming (TODO: support reading)\n", device_name);
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;
223 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
224 printf(
"[v4l2] Could not set data format settings of %s\n", device_name);
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);
241 if (buffers == NULL) {
242 printf(
"[v4l2] Not enough memory for %s to initialize %d MMAP buffers\n", device_name, req.count);
248 for (i = 0; i < req.count; ++i) {
249 struct v4l2_buffer buf;
253 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
254 buf.memory = V4L2_MEMORY_MMAP;
256 if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
257 printf(
"[v4l2] Querying buffer %d from %s failed\n", i, device_name);
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);
277 dev->
name = strdup(device_name);
302 pthread_mutex_lock(&dev->
mutex);
310 pthread_mutex_unlock(&dev->
mutex);
337 pthread_mutex_lock(&dev->
mutex);
342 pthread_mutex_unlock(&dev->
mutex);
368 struct v4l2_buffer buf;
372 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
373 buf.memory = V4L2_MEMORY_MMAP;
375 if (ioctl(dev->
fd, VIDIOC_QBUF, &buf) < 0) {
376 printf(
"[v4l2] Could not enqueue %d for %s\n", img->
buf_idx, dev->
name);
390 enum v4l2_buf_type type;
393 if (dev->
thread != (pthread_t)NULL) {
394 printf(
"[v4l2] There is already a capturing thread running for %s\n", dev->
name);
401 struct v4l2_buffer buf;
404 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
405 buf.memory = V4L2_MEMORY_MMAP;
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);
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));
423 printf(
"[v4l2] Could not start capturing thread for %s (return code: %d)\n", dev->
name, rc);
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);
432 dev->
thread = (pthread_t) NULL;
448 enum v4l2_buf_type type;
451 if (dev->
thread == (pthread_t) NULL) {
452 printf(
"[v4l2] Already stopped capture for %s\n", dev->
name);
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);
464 if (pthread_cancel(dev->
thread) < 0) {
465 printf(
"[v4l2] Could not cancel thread for %s\n", dev->
name);
470 pthread_join(dev->
thread, NULL);
471 dev->
thread = (pthread_t) NULL;
491 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.
bool_t v4l2_start_capture(struct v4l2_device *dev)
Start capturing images in streaming mode (Thread safe)
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...
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)
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 ...
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 ...
uint8_t buf_idx
Buffer index for V4L2 freeing.
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.
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...
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.
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.
UYVY format (uint16 per pixel)
uint8_t buffers_cnt
The number of image buffers.
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...
volatile uint8_t buffers_deq_idx
The current dequeued index.
pthread_t thread
The thread that handles the images.
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.
uint16_t w
The width of the image.
enum image_type type
The image type.
int fd
The file pointer to the device.