简体   繁体   English

v4l2中的网络摄像头设备的读取功能失败,并带有无效参数

[英]read function for webcam device in v4l2 fails with invalid argument

I have write a simple program in C99 for v4l2 and according to many Linux books it should work but I get Invalid argument error for read api. 我已经在C99中为v4l2编写了一个简单程序,根据许多Linux书籍,它应该可以工作,但是读取api时出现Invalid argument错误。 what do I have forget? 我忘记了什么?

int main(int argc, char** argv)
{
    int fd = open("/dev/video0", O_RDWR);
    if (fd == -1) {
        perror("Error opening");
        exit(EXIT_FAILURE);
    }


    struct v4l2_format format; //Query Format structure
    memset(&format, 0, sizeof(format));
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    int status = ioctl(fd, VIDIOC_G_FMT, &format);
    if (status == -1) {
        perror("Error querying format");
        exit(EXIT_FAILURE);
    }

    size_t width = format.fmt.pix.width; //Image width
    size_t height = format.fmt.pix.height; //Image height
    size_t imageSize = format.fmt.pix.sizeimage; // Total image size in bytes
    size_t pixelFmt = format.fmt.pix.pixelformat; // Pixel format
    printf("width:%u, height:%u, size:%u", width, height, imageSize);
    switch(pixelFmt) {
    case V4L2_PIX_FMT_YUYV:
        printf(" & format: YuYv\n");
        break;
    case V4L2_PIX_FMT_RGB24:
        printf(" & format: RGB24\n");
        break;
    default:
        printf(" & format: %u\n", pixelFmt);
    }

    char* buf = malloc(imageSize);  // Image buffer
    if(buf == NULL) {
        perror("Error allocating buffer");
        exit(EXIT_FAILURE);
    }

    fd_set fds; //Select descriptors
    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    struct timeval tv; //Timeout specification structure
    tv.tv_sec = 20;
    tv.tv_usec = 0;

    while(true) {

        status = select(fd+1, &fds, NULL, NULL, &tv);

        if (status == -1) {
            perror("Error selecting");
            exit(EXIT_FAILURE);
        } else if(status == 0) {
            perror("Select timeout");
            exit(EXIT_FAILURE);
        }

        status = read(fd, buf, imageSize);
        if (status == -1) {
            perror("Error reading");
            exit(EXIT_FAILURE);
        }

    }

    free(buf);
    close(fd);

    return EXIT_SUCCESS;
}

I am sure that the webcame is working and v4l2 library is installed in my Linux following is the complete output: 我确定网络摄像头正在运行,并且在我的Linux中安装了v4l2库,以下是完整的输出:

width:640, height:480, size:614400 & format: YuYv
Error reading: Invalid argument

You should use the following code fragment to capture video data 您应该使用以下代码片段捕获视频数据

struct v4l2_requestbuffers reqbuf;
reqbuf.count = BUFFER_COUNT;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;

ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);
if(ret < 0) {
    perror("VIDIOC_REQBUFS: ");
    return ret;
}

struct v4l2_buffer buf;
for (i = 0; i < reqbuf.count; i++) {
    buf.index = i;
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);
    if(ret < 0) {
        perror("VIDIOC_QUERYBUF: ");
        return ret;
    }
    framebuf[i].length = buf.length;
    framebuf[i].start = (char *) mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
}

enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_STREAMON, &type);
if (ret < 0) {
    perror("VIDIOC_STREAMON: ");
    return ret;
}

ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if (ret < 0) {
    perror("VIDIOC_DQBUF ");
    return ret;
}

// access the captured data via framebuf[buf.index].start

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM