Hi Ricardo and Dan,

could you please try the attached patch and see if it helps ?

Best regards,

Laurent Pinchart
Index: uvc_video.c
===================================================================
--- uvc_video.c	(revision 209)
+++ uvc_video.c	(working copy)
@@ -64,6 +64,31 @@
 				UVC_CTRL_CONTROL_TIMEOUT);
 }
 
+static void uvc_fixup_buffer_size(struct uvc_video_device *video,
+	struct uvc_streaming_control *ctrl)
+{
+	struct uvc_format *format;
+	struct uvc_frame *frame;
+
+	if (ctrl->bFormatIndex <= 0 ||
+	    ctrl->bFormatIndex > video->streaming->nformats)
+		return;
+
+	format = &video->streaming->format[ctrl->bFormatIndex - 1];
+
+	if (ctrl->bFrameIndex <= 0 ||
+	    ctrl->bFrameIndex > format->nframes)
+		return;
+
+	frame = &format->frame[ctrl->bFrameIndex - 1];
+
+	if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
+	     (ctrl->dwMaxVideoFrameSize == 0 &&
+	      video->dev->uvc_version < 0x0110))
+		ctrl->dwMaxVideoFrameSize =
+			frame->dwMaxVideoFrameBufferSize;
+}
+
 static int uvc_get_video_ctrl(struct uvc_video_device *video,
 	struct uvc_streaming_control *ctrl, int probe, __u8 query)
 {
@@ -108,26 +133,11 @@
 		ctrl->bMaxVersion = 0;
 	}
 
-	if (ctrl->dwMaxVideoFrameSize == 0 &&
-	    video->dev->uvc_version < 0x0110) {
-		/* Some broken UVC 1.0 devices return a null
-		 * dwMaxVideoFrameSize. Try to get the value from the format
-		 * and frame descriptor.
-		 */
-		const unsigned int fmt_index = ctrl->bFormatIndex;
-		const unsigned int frm_index = ctrl->bFrameIndex;
-		struct uvc_format *format = NULL;
-		struct uvc_frame *frame = NULL;
+	/* Some broken devices return a null or wrong dwMaxVideoFrameSize.
+	 * Try to get the value from the format and frame descriptor.
+	 */
+	uvc_fixup_buffer_size(video, ctrl);
 
-		if (fmt_index <= video->streaming->nformats && fmt_index != 0)
-			format = &video->streaming->format[fmt_index - 1];
-		if (format && frm_index <= format->nframes && frm_index != 0) {
-			frame = &format->frame[frm_index - 1];
-			ctrl->dwMaxVideoFrameSize =
-				frame->dwMaxVideoFrameBufferSize;
-		}
-	}
-
 	return 0;
 }
 
Index: uvc_driver.c
===================================================================
--- uvc_driver.c	(revision 209)
+++ uvc_driver.c	(working copy)
@@ -452,6 +452,18 @@
 		}
 		frame->dwFrameInterval = *intervals;
 
+		/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
+		 * completely. Observed behaviours range from setting the
+		 * value to 1.1x the actual frame size of hardwiring the
+		 * 16 low bits to 0. This results in a higher than necessary
+		 * memory usage as well as a wrong image size information. For
+		 * uncompressed formats this can be fixed by computing the
+		 * value from the frame size.
+		 */
+		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
+			frame->dwMaxVideoFrameBufferSize = format->bpp
+				* frame->wWidth * frame->wHeight / 8;
+
 		/* Some bogus devices report dwMinFrameInterval equal to
 		 * dwMaxFrameInterval and have dwFrameIntervalStep set to
 		 * zero. Setting all null intervals to 1 fixes the problem and
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel

Reply via email to