Просмотр исходного кода

Log error when the VIDIOC_SUBDEV_S_FMT call applies another mode than requested.

Martijn Braam 3 месяцев назад
Родитель
Сommit
2f369fbab1
1 измененных файлов с 34 добавлено и 6 удалено
  1. 34 6
      src/pipeline.c

+ 34 - 6
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;