Захват видеокадров и запись в файл V4L2 С++

У меня стоит задача разработать программу, которая будет захватывать видео с USB видеокамеры и сохранять в файл. Я использую библиотеку V4L2 и OpenCV.

Выдает ошибку, на открытие потока видео:

 if (ioctl(fd, VIDIOC_STREAMON, &buf.type) == -1) {
        perror("Error starting video stream");
        return 1;
    }

Думаю, что проблема с форматом

fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; Мой код:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <linux/videodev2.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/v4l2-common.h>
#include <linux/v4l2-controls.h>
#include <linux/videodev2.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <fstream>
#include <string>

using namespace std;
using namespace cv;

int main() {
    cout << "Starting camera capture..." << endl;

    // Открываем устройство видеозахвата
    const char* device = "/dev/video0";
    int fd = open(device, O_RDWR);

    if (fd == -1) {
        perror("Error opening device");
        return 1;
    }

    // Задаем формат видео и разрешение
    struct v4l2_format fmt = {0};
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = 1920;
    fmt.fmt.pix.height = 1080;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//YUYV

    if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
        perror("Error setting video format");
        return 1;
    }

    // Запускаем поток видеозахвата
    struct v4l2_requestbuffers req = {0};
    req.count = 4;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;

    if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
        perror("Error requesting buffer");
        return 1;
    }

    struct v4l2_buffer buf = {0};
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    for (int i = 0; i < req.count; i++) {
        buf.index = i;

        if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
            perror("Error querying buffer");
            return 1;
        }

        void* buffer = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);

        if (buffer == MAP_FAILED) {
            perror("Error mapping buffer");
            return 1;
        }

        if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
            perror("Error queueing buffer");
            return 1;
        }
    }
    //Делаем захват видеокадров
cout << " +"<<endl;
    if (ioctl(fd, VIDIOC_STREAMON, &buf.type) == -1) {
        perror("Error starting video stream");
        return 1;
    }
    cout << " -"<<endl;



    // Создаем объект для записи видео в файл
    VideoWriter writer("output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 25, Size(1920, 1080), true);

    if (!writer.isOpened()) {
        cerr << "Error opening output video file" << endl;
        return 1;
    }

    // Захватываем кадры и записываем в файл
    Mat frame;

    for (int i = 0; i < 300; i++) { // Записываем 300 кадров
        if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {
            perror("Error dequeuing buffer");
            return 1;
        }

        memcpy(frame.data, (void*)buf.m.offset, buf.bytesused);
                if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
                    perror("Error queueing buffer");
                    return 1;
                }

                writer.write(frame);
            }

            // Остановка потока видеозахвата и освобождение ресурсов
            if (ioctl(fd, VIDIOC_STREAMOFF, &buf.type) == -1) {
                perror("Error stopping video stream");
                return 1;
            }

            for (int i = 0; i < req.count; i++) {
                if (munmap(NULL, buf.length) == -1) {
                    perror("Error unmapping buffer");
                    return 1;
                }
            }

            close(fd);

            cout << "Finished capturing and saving video." << endl;

            return 0;
}

Ответы (0 шт):