Захват видеокадров и запись в файл 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;
}