From 2f369fbab166defebf12dff7b43ea8b047a17a70 Mon Sep 17 00:00:00 2001 From: Martijn Braam Date: Wed, 14 Feb 2024 01:32:09 +0100 Subject: [PATCH] Log error when the VIDIOC_SUBDEV_S_FMT call applies another mode than requested. --- src/pipeline.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/pipeline.c b/src/pipeline.c index eae1092..992289d 100644 --- a/src/pipeline.c +++ b/src/pipeline.c @@ -227,12 +227,6 @@ libmegapixels_select_mode(libmegapixels_camera *camera, libmegapixels_mode *mode } break; case LIBMEGAPIXELS_CMD_MODE: - subdev_fmt.pad = cmd->pad_from; - subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - subdev_fmt.format.width = cmd->width; - subdev_fmt.format.height = cmd->height; - subdev_fmt.format.code = libmegapixels_format_to_media_busfmt(cmd->format); - subdev_fmt.format.field = V4L2_FIELD_ANY; log_debug(" Mode %s:%d [%dx%d %s]\n", cmd->entity_from, cmd->pad_from, cmd->width, cmd->height, libmegapixels_format_name(cmd->format)); @@ -256,9 +250,43 @@ libmegapixels_select_mode(libmegapixels_camera *camera, libmegapixels_mode *mode } } + subdev_fmt.pad = cmd->pad_from; + subdev_fmt.which = V4L2_SUBDEV_FORMAT_TRY; + subdev_fmt.format.width = cmd->width; + subdev_fmt.format.height = cmd->height; + subdev_fmt.format.code = libmegapixels_format_to_media_busfmt(cmd->format); + subdev_fmt.format.field = V4L2_FIELD_ANY; + + if (xioctl(sd->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt) == -1) { + log_error("Could not try mode on %s:%d: %s\n", cmd->entity_from, cmd->pad_from, strerror(errno)); + } + + if (subdev_fmt.format.width != cmd->width || subdev_fmt.format.height != cmd->height) { + log_error("Driver rejected resolution %dx%d, changed to %dx%d\n", cmd->width, cmd->height, + subdev_fmt.format.width, subdev_fmt.format.height); + break; + } + if (subdev_fmt.format.code != libmegapixels_format_to_media_busfmt(cmd->format)) { + log_error("Driver rejected pixfmt try: %d\n", subdev_fmt.format.code); + break; + } + subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; if (xioctl(sd->fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt) == -1) { log_error("Could not set mode on %s:%d: %s\n", cmd->entity_from, cmd->pad_from, strerror(errno)); } + + // There seem to be drivers that don't reject resolutions in V4L2_SUBDEV_FORMAT_TRY mode but + // do silently change the resolution when doing the V4L2_SUBDEV_FORMAT_ACTIVE bit. So check + // again since V4L2 is the wild west. + if (subdev_fmt.format.width != cmd->width || subdev_fmt.format.height != cmd->height) { + log_error("Driver rejected resolution %dx%d, changed to %dx%d\n", cmd->width, cmd->height, + subdev_fmt.format.width, subdev_fmt.format.height); + break; + } + if (subdev_fmt.format.code != libmegapixels_format_to_media_busfmt(cmd->format)) { + log_error("Driver rejected pixfmt: %d\n", subdev_fmt.format.code); + break; + } break; case LIBMEGAPIXELS_CMD_INTERVAL: subdev_ival.pad = cmd->pad_from;