67 lines
2.8 KiB
C++
67 lines
2.8 KiB
C++
#pragma once
|
|
#include <QByteArray>
|
|
#include "debug_config.h"
|
|
#ifdef Q_OS_LINUX
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/videodev2.h>
|
|
#include <cerrno>
|
|
#include <cstring>
|
|
#endif
|
|
|
|
// Qt задаёт 30 fps, но UVC auto-exposure может разрешить камере снижать их до 16–17.
|
|
// Меняем только этот флаг на время захвата; сама автоэкспозиция остаётся включённой.
|
|
class CallCameraRate {
|
|
#ifdef Q_OS_LINUX
|
|
int fd = -1;
|
|
#endif
|
|
public:
|
|
CallCameraRate() = default;
|
|
CallCameraRate(const CallCameraRate&) = delete;
|
|
CallCameraRate& operator=(const CallCameraRate&) = delete;
|
|
~CallCameraRate() { restore(); }
|
|
void restore() {
|
|
#ifdef Q_OS_LINUX
|
|
if (fd < 0) return;
|
|
v4l2_control control{}; control.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY; control.value = 1;
|
|
if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0)
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call camera dynamic fps restore failed: %s", std::strerror(errno));
|
|
else DEBUG_INFO(DEBUG_CATEGORY_CALL, "call camera dynamic fps restored=1");
|
|
::close(fd); fd = -1;
|
|
#endif
|
|
}
|
|
void activate(const QByteArray& device) {
|
|
restore();
|
|
#ifdef Q_OS_LINUX
|
|
if (!device.startsWith("/dev/video")) {
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "call camera fps policy unavailable device=%s", device.constData()); return;
|
|
}
|
|
int camera = ::open(device.constData(), O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
|
if (camera < 0) {
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call camera fps control open failed device=%s: %s", device.constData(), std::strerror(errno));
|
|
return;
|
|
}
|
|
v4l2_control control{}; control.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
|
|
if (ioctl(camera, VIDIOC_G_CTRL, &control) < 0) {
|
|
if (errno == EINVAL) DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "call camera dynamic fps control unsupported device=%s", device.constData());
|
|
else DEBUG_WARN(DEBUG_CATEGORY_CALL, "call camera fps control read failed: %s", std::strerror(errno));
|
|
} else if (!control.value) {
|
|
DEBUG_INFO(DEBUG_CATEGORY_CALL, "call camera dynamic fps already disabled device=%s", device.constData());
|
|
} else {
|
|
control.value = 0;
|
|
if (ioctl(camera, VIDIOC_S_CTRL, &control) < 0)
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call camera dynamic fps disable failed: %s", std::strerror(errno));
|
|
else {
|
|
fd = camera;
|
|
DEBUG_INFO(DEBUG_CATEGORY_CALL, "call camera dynamic fps disabled device=%s; auto exposure retained", device.constData());
|
|
return;
|
|
}
|
|
}
|
|
::close(camera);
|
|
#else
|
|
Q_UNUSED(device);
|
|
#endif
|
|
}
|
|
};
|