diff --git a/src/device.c b/src/device.c index 7859adf..5a07565 100644 --- a/src/device.c +++ b/src/device.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,7 @@ static int _device_open_format(struct device_t *dev); static void _device_open_alloc_picbufs(struct device_t *dev); static int _device_open_mmap(struct device_t *dev); static int _device_open_queue_buffers(struct device_t *dev); +static int _device_apply_resolution(struct device_t *dev, const unsigned width, const unsigned height); static const char *_format_to_string_auto(char *buf, const size_t size, const unsigned format); static const char *_format_to_string_null(const unsigned format); @@ -222,6 +224,7 @@ static int _device_open_check_cap(struct device_t *dev) { } static int _device_open_dv_timings(struct device_t *dev) { + _device_apply_resolution(dev, dev->width, dev->height); if (dev->dv_timings) { LOG_DEBUG("Using DV-timings"); @@ -239,10 +242,6 @@ static int _device_open_dv_timings(struct device_t *dev) { LOG_PERROR("Can't subscribe to V4L2_EVENT_SOURCE_CHANGE"); return -1; } - - } else { - dev->run->width = dev->width; - dev->run->height = dev->height; } return 0; } @@ -267,8 +266,9 @@ static int _device_apply_dv_timings(struct device_t *dev) { return -1; } - dev->run->width = dv_timings.bt.width; - dev->run->height = dv_timings.bt.height; + if (_device_apply_resolution(dev, dv_timings.bt.width, dv_timings.bt.height) < 0) { + return -1; + } } else { LOG_DEBUG("Calling ioctl(VIDIOC_QUERYSTD) ..."); @@ -311,8 +311,9 @@ static int _device_open_format(struct device_t *dev) { if (fmt.fmt.pix.width != dev->run->width || fmt.fmt.pix.height != dev->run->height) { LOG_ERROR("Requested resolution=%dx%d is unavailable", dev->run->width, dev->run->height); } - dev->run->width = fmt.fmt.pix.width; - dev->run->height = fmt.fmt.pix.height; + if (_device_apply_resolution(dev, fmt.fmt.pix.width, fmt.fmt.pix.height) < 0) { + return -1; + } LOG_INFO("Using resolution: %dx%d", dev->run->width, dev->run->height); // Check format @@ -421,6 +422,22 @@ static void _device_open_alloc_picbufs(struct device_t *dev) { } } +static int _device_apply_resolution(struct device_t *dev, const unsigned width, const unsigned height) { + // Тут VIDEO_MIN_* не используются из-за странностей минимального разрешения при отсутствии сигнала + // у некоторых устройств, например Auvidea B101 + if ( + width == 0 || width > VIDEO_MAX_WIDTH + || height == 0 || height > VIDEO_MAX_HEIGHT + ) { + LOG_ERROR("Requested forbidden resolution=%ux%u: min=1x1; max=%ux%u", + width, height, VIDEO_MAX_WIDTH, VIDEO_MAX_HEIGHT); + return -1; + } + dev->run->width = width; + dev->run->height = height; + return 0; +} + static const char *_format_to_string_auto(char *buf, const size_t size, const unsigned format) { assert(size >= 8); buf[0] = format & 0x7f; diff --git a/src/device.h b/src/device.h index 68f2458..b4551c4 100644 --- a/src/device.h +++ b/src/device.h @@ -28,6 +28,12 @@ #include +#define VIDEO_MIN_WIDTH 320 +#define VIDEO_MAX_WIDTH 1920 + +#define VIDEO_MIN_HEIGHT 180 +#define VIDEO_MAX_HEIGHT 1200 + #define STANDARD_UNKNOWN V4L2_STD_UNKNOWN #define STANDARDS_STR "UNKNOWN, PAL, NTSC, SECAM" diff --git a/src/main.c b/src/main.c index 4351a6b..11717fc 100644 --- a/src/main.c +++ b/src/main.c @@ -176,8 +176,8 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e switch (ch) { case 'd': OPT_SET(dev->path, optarg); case 'i': OPT_UNSIGNED(dev->input, "--input", 0, 128); - case 'x': OPT_UNSIGNED(dev->width, "--width", 320, 1920); - case 'y': OPT_UNSIGNED(dev->height, "--height", 180, 1200); + case 'x': OPT_UNSIGNED(dev->width, "--width", VIDEO_MIN_WIDTH, VIDEO_MAX_WIDTH); + case 'y': OPT_UNSIGNED(dev->height, "--height", VIDEO_MIN_HEIGHT, VIDEO_MAX_HEIGHT); # pragma GCC diagnostic ignored "-Wsign-compare" # pragma GCC diagnostic push case 'm': OPT_PARSE(dev->format, device_parse_format, FORMAT_UNKNOWN, "pixel format");