4#ifndef OPENSHOT_CAMERA_CAPTURE_V4L2_H
5#define OPENSHOT_CAMERA_CAPTURE_V4L2_H
11#include <linux/videodev2.h>
17namespace openshot {
namespace detail {
18using CameraIoctl = std::function<int(
unsigned long,
void*)>;
20inline bool CameraQuery(
const CameraIoctl& query,
unsigned long request,
void* value)
23 do { result = query(request, value); }
while (result < 0 && errno == EINTR);
24 if (result >= 0)
return true;
25 if (errno == EINVAL || errno == ENOTTY)
return false;
26 throw std::runtime_error(
"Unable to enumerate V4L2 camera modes (errno " + std::to_string(errno) +
").");
29inline std::string CameraInputFormat(
unsigned int format)
32 case V4L2_PIX_FMT_MJPEG:
return "mjpeg";
33 case V4L2_PIX_FMT_JPEG:
return "mjpeg";
34 case V4L2_PIX_FMT_H264:
return "h264";
35 case V4L2_PIX_FMT_YUYV:
return "yuyv422";
36 case V4L2_PIX_FMT_UYVY:
return "uyvy422";
37 case V4L2_PIX_FMT_NV12:
return "nv12";
38 case V4L2_PIX_FMT_YUV420:
return "yuv420p";
39 case V4L2_PIX_FMT_RGB24:
return "rgb24";
40 case V4L2_PIX_FMT_BGR24:
return "bgr24";
41 case V4L2_PIX_FMT_GREY:
return "gray";
46inline std::vector<CameraCaptureMode> EnumerateCameraModes(
const CameraIoctl& query)
48 std::vector<CameraCaptureMode> modes;
49 auto add = [&](
unsigned int width,
unsigned int height,
const std::string& format, v4l2_fract interval) {
50 if (!width || !height || width > INT_MAX || height > INT_MAX ||
51 !interval.numerator || !interval.denominator ||
52 interval.numerator > INT_MAX || interval.denominator > INT_MAX)
return;
53 CameraCaptureMode mode;
56 mode.input_format = format;
57 mode.fps = Fraction(interval.denominator, interval.numerator);
59 for (
const auto& existing : modes)
60 if (existing.width == mode.width && existing.height == mode.height &&
61 existing.input_format == mode.input_format && existing.fps.num == mode.fps.num &&
62 existing.fps.den == mode.fps.den)
return;
63 modes.push_back(mode);
65 for (
unsigned int f = 0; ; ++f) {
66 v4l2_fmtdesc format = {};
68 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
69 if (!CameraQuery(query, VIDIOC_ENUM_FMT, &format))
break;
70 const auto input_format = CameraInputFormat(format.pixelformat);
71 if (input_format.empty())
continue;
72 for (
unsigned int s = 0; ; ++s) {
73 v4l2_frmsizeenum size = {};
75 size.pixel_format = format.pixelformat;
76 if (!CameraQuery(query, VIDIOC_ENUM_FRAMESIZES, &size))
break;
77 std::vector<std::pair<unsigned int, unsigned int>> sizes;
78 if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE)
79 sizes.emplace_back(size.discrete.width, size.discrete.height);
80 else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE || size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
81 sizes.emplace_back(size.stepwise.min_width, size.stepwise.min_height);
82 sizes.emplace_back(size.stepwise.max_width, size.stepwise.max_height);
84 for (
const auto& dimensions : sizes) {
85 for (
unsigned int i = 0; ; ++i) {
86 v4l2_frmivalenum interval = {};
88 interval.pixel_format = format.pixelformat;
89 interval.width = dimensions.first;
90 interval.height = dimensions.second;
91 if (!CameraQuery(query, VIDIOC_ENUM_FRAMEINTERVALS, &interval))
break;
92 if (interval.type == V4L2_FRMIVAL_TYPE_DISCRETE)
93 add(interval.width, interval.height, input_format, interval.discrete);
94 else if (interval.type == V4L2_FRMIVAL_TYPE_STEPWISE || interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
95 add(interval.width, interval.height, input_format, interval.stepwise.min);
96 add(interval.width, interval.height, input_format, interval.stepwise.max);
98 if (interval.type != V4L2_FRMIVAL_TYPE_DISCRETE)
break;
101 if (size.type != V4L2_FRMSIZE_TYPE_DISCRETE)
break;
Header file for live camera capture readers.
This namespace is the default namespace for all code in the openshot library.