I'v written a simple C shared object library which calls v4l2(Video for Linux two) API eg v4l2_open(). Then I'm trying to poll() on the returned device handle but it always return POLLERR in the revents. I tried different parameters with timeout but it does not help. Here is the complete code.
/*
* libwebcam.h
*
* Created on: 13.04.2016
* Author: max
*/
#ifndef LIBWEBCAM_H_
#define LIBWEBCAM_H_
#include <stdint.h>
struct webcam
{
int fd;
uint32_t width;
uint32_t height;
uint32_t sizeimage;
uint32_t bytesperline;
uint8_t *image_buffer;
void *priv_data;
};
int webcam_open(struct webcam *w);
int webcam_close(struct webcam *w);
int webcam_take_image(struct webcam *w);
int webcam_poll(struct webcam *w);
#endif /* LIBWEBCAM_H_ */
/*
* libwebcam.c
*
* Created on: 13.04.2016
* Author: max
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <libv4l2.h>
#include <poll.h>
#include "libwebcam.h"
int webcam_open(struct webcam *w)
{
struct v4l2_capability caps;
struct v4l2_format fmt;
int dev_index;
int dev;
char buffer[255];
for (dev_index = 0; dev_index < 64; dev_index++) {
memset(&buffer, 0, sizeof(buffer));
sprintf(buffer, "/dev/video%d", dev_index);
#ifdef DEBUG
printf("libwebcam: Probing %s\n", buffer);
#endif
dev = v4l2_open(buffer, O_RDWR | O_NONBLOCK, 0);
if (dev != -1) {
memset(&caps, 0, sizeof(caps));
if (v4l2_ioctl(dev, VIDIOC_QUERYCAP, &caps) == -1) {
return -1;
}
if (caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
#ifdef DEBUG
printf("libwebcam: %s is video capture device\n", buffer);
#endif
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(v4l2_ioctl(dev, VIDIOC_G_FMT, &fmt) == -1) {
return -1;
}
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
if(v4l2_ioctl(dev, VIDIOC_S_FMT, &fmt) == -1) {
return -1;
}
if(v4l2_ioctl(dev, VIDIOC_G_FMT, &fmt) == -1) {
return -1;
}
if(w)
{
w->fd = dev;
w->bytesperline = fmt.fmt.pix.bytesperline;
w->height = fmt.fmt.pix.height;
w->sizeimage = fmt.fmt.pix.sizeimage;
w->width = fmt.fmt.pix.width;
w->image_buffer = calloc(fmt.fmt.pix.sizeimage, sizeof(uint8_t));
if(w->image_buffer == NULL)
return -1;
w->priv_data = calloc(1, sizeof(struct pollfd));
if(w->priv_data == NULL)
return -1;
return 0;
}
else
{
errno = EINVAL;
return -1;
}
}
}
}
errno = ENODEV;
return -1;
}
int webcam_close(struct webcam *w)
{
if(w)
{
if(w->image_buffer != NULL){
free(w->image_buffer);
w->image_buffer = NULL;
}
if(w->priv_data != NULL) {
free(w->priv_data);
w->priv_data = NULL;
}
if(w->fd != -1)
if(v4l2_close(w->fd) == -1)
return -1;
return 0;
}
errno = EINVAL;
return -1;
}
int webcam_take_image(struct webcam *w)
{
if(w)
{
return v4l2_read(w->fd, w->image_buffer, w->sizeimage * sizeof(uint8_t));
}
errno = EINVAL;
return -1;
}
int webcam_poll(struct webcam *w)
{
if(w)
{
((struct pollfd *)w->priv_data)->events = POLLIN;
((struct pollfd *)w->priv_data)->revents = 0;
((struct pollfd *)w->priv_data)->fd = w->fd;
if(poll(((struct pollfd*)w->priv_data), 1, -1) == -1)
{
return -1;
}
if(((struct pollfd*)w->priv_data)->revents & POLLIN) {
#ifdef DEBUG
printf("libwebcam: Data is available...\n");
#endif
return 1;
}
if(((struct pollfd*)w->priv_data)->revents & POLLERR) {
#ifdef DEBUG
printf("libwebcam: Error in poll...\n");
#endif
return -1;
}
#ifdef DEBUG
printf("libwebcam: Timeout...\n");
#endif
return 0;
}
#ifdef DEBUG
printf("libwebcam: Struct not valid...\n");
#endif
errno = EINVAL;
return -1;
}
/*
* test.c
*
* Created on: 14.04.2016
* Author: max
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libwebcam.h>
int main(int argc, char **argv)
{
struct webcam w;
int polled;
memset(&w, 0, sizeof(w));
if(webcam_open(&w) == -1)
{
perror("Unable to find webcam");
return EXIT_FAILURE;
}
while(1)
{
polled = webcam_poll(&w);
if(polled == -1)
{
perror("Error in poll");
return EXIT_FAILURE;
}
if(polled == 1)
{
webcam_take_image(&w);
}
}
if(webcam_close(&w) == -1)
{
perror("Unable to close webcam");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Can anyone tell me what is going on in the code?
I tested your code, and on my system the poll
call is returning 0. From the man page, "A value of 0 indicates that the call timed out and no file descriptors were ready." So you should test for 0 in addition to -1 and 1.
I don't know why it fills in revents
with POLLERR
, but I would only check the resulting revents
field if poll
returned 1.
Also, not all V4L2 devices support read()
, so you should check that your device supports it by testing caps.capabilities & V4L2_CAP_READWRITE
. My laptop webcam where I tested this does not support read/write.
See this example program for reference.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.