v4l2 VIDIOC_STREAMON 出错

运行到 ioctl(Dev, VIDIOC_STREAMON, &Type);
输出main() VIDIOC_STREAMON V4L2_BUF_TYPE_VIDEO_OUTPUT failed errno(22) Invalid argument
可能是什么原因导致的呢

在运行到 ioctl(Dev, VIDIOC_STREAMON, &Type) 时,输出 VIDIOC_STREAMON V4L2_BUF_TYPE_VIDEO_OUTPUT failed errno(22) Invalid argument,这可能是由于设备不支持视频输出或者输入格式设置有误导致的。

请检查以下几点:

  1. 确认设备是否支持视频输出功能。如果设备不支持输出,则应该使用 V4L2_BUF_TYPE_VIDEO_CAPTURE 类型。
  2. 确保格式设置正确。将 struct v4l2_format 中的 type 成员设置为 V4L2_BUF_TYPE_VIDEO_CAPTURE 或 V4L2_BUF_TYPE_VIDEO_OUTPUT,并根据设备要求设置 fmt 成员中的参数。
    下面是一份修改后的代码示例,仅供参考:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>

#define WIDTH 640
#define HEIGHT 480
#define FPS 30

int main() {
    int fd = open("/dev/video0", O_RDWR);
    if (fd == -1) {
        printf("Error: Cannot open device video0\n");
        return -1;
    }

    struct v4l2_capability cap;
    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
        printf("Error: Cannot query device capabilities\n");
        close(fd);
        return -1;
    }

    struct v4l2_format fmt;
    memset(&fmt, 0, sizeof(fmt));
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = WIDTH;
    fmt.fmt.pix.height = HEIGHT;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    fmt.fmt.pix.field = V4L2_FIELD_NONE;
    if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
        printf("Error: Cannot set format\n");
        close(fd);
        return -1;
    }

    struct v4l2_requestbuffers reqbuf;
    memset(&reqbuf, 0, sizeof(reqbuf));
    reqbuf.count = 4;
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
        printf("Error: Cannot request buffers\n");
        close(fd);
        return -1;
    }

    struct v4l2_buffer buffer[4];
    void* start[4];
    for (int i = 0; i < reqbuf.count; i++) {
        memset(&buffer[i], 0, sizeof(buffer[i]));
        buffer[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buffer[i].memory = V4L2_MEMORY_MMAP;
        buffer[i].index = i;
        if (ioctl(fd, VIDIOC_QUERYBUF, &buffer[i]) == -1) {
            printf("Error: Cannot query buffer\n");
            close(fd);
            return -1;
        }
        start[i] = mmap(NULL, buffer[i].length, PROT_READ | PROT_WRITE,
                         MAP_SHARED, fd, buffer[i].m.offset);
        if (start[i] == MAP_FAILED) {
            printf("Error: Cannot mmap buffer\n");
            close(fd);
            return -1;
        }
    }

    for (int i = 0; i < reqbuf.count; i++) {
        if (ioctl(fd, VIDIOC_QBUF, &buffer[i]) == -1) {
            printf("Error: Cannot queue buffer\n");
            close(fd);
            return -1;
        }
    }

    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
        printf("Error: Cannot start streaming\n");
        close(fd);
        return -1;
    }

    int frame_count = 100;
    while (frame_count-- > 0) {
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(fd, &fds);

        struct timeval timeout;
        timeout.tv_sec = 2;
        timeout.tv_usec = 0;

        int ret = select(fd + 1, &fds, NULL, NULL, &timeout);
        if (ret == -1) {
            printf("Error: Cannot waiting for data\n");
            close(fd);
            return -1
        }
}