Files
utun2/tools/chatgui/src/call_camera_rate.h
T

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
}
};