Hallo all,

here is patch (against current master git) to add two new quirks and
some more debug string to see what happening :D 

The quirks are:
UVC_QUIRK_FIX_JPEG_BANDWIDTH   0x00000040
/* to recalculate bandwidth needed for jpeg compressed stream */
UVC_QUIRK_DISABLE_URB_1024     0x00000400
/* by default we use safe bandwith restriction, to less than 1024 *
 * this quirk disables this restriction. So if you need URB less than 
 * 1024, use this quirk. It will work only with FIX*BANDWIDTH quirk. */

Also i added module option "jpeg_comp" to change calculation for
bandwith. Default is 4bpp, 1 is maximal compression, 16bpp is no
compression, just normal raw stream.

This patch also gather statistic about used buffers. It will report
biggest used buffer. You will need it to calculate best value for
jpeg_comp option.

Usage. Recalculate bandwidth for jpeg and disable 1024 restriction:
sudo rmmod uvcvideo && sudo modprobe quirks=0x440

reduce calculated bandwith to minimum:
sudo rmmod uvcvideo && sudo modprobe quirks=0x440 jpeg_comp=1

for more info enable trace=0xffff and seek for messages like:
...
[25495.869580] uvcvideo: Device requested 703 B/frame bandwidth.
[25495.869583] uvcvideo: Selecting alternate setting 5 (800 B/frame
bandwidth).
[25495.869758] uvcvideo: Allocated 5 URB buffers of 32x800 bytes each.
...
[25501.959475] uvcvideo: Biggest used buffer: 1382400/106438. Format:
MJPEG 960x720@15.

-- 
Regards,
        Alexey
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 6459b8c..7ab9e3d 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -47,6 +47,7 @@ unsigned int uvc_no_drop_param;
 static unsigned int uvc_quirks_param = -1;
 unsigned int uvc_trace_param;
 unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
+unsigned int uvc_jpeg_comp_param;
 
 /* ------------------------------------------------------------------------
  * Video formats
@@ -348,7 +349,10 @@ static int uvc_parse_format(struct uvc_device *dev,
 		strlcpy(format->name, "MJPEG", sizeof format->name);
 		format->fcc = V4L2_PIX_FMT_MJPEG;
 		format->flags = UVC_FMT_FLAG_COMPRESSED;
-		format->bpp = 0;
+		if ((uvc_jpeg_comp_param > 0) && ( 16 >= uvc_jpeg_comp_param))
+			format->bpp = uvc_jpeg_comp_param;
+		else
+			format->bpp = 4;
 		ftype = UVC_VS_FRAME_MJPEG;
 		break;
 
@@ -1954,6 +1958,10 @@ module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(trace, "Trace level bitmask");
 module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
+module_param_named(jpeg_comp, uvc_jpeg_comp_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(jpeg_comp, "Overvrite default compression value for jpeg."
+			    "This needed to recalculate bandwidth."
+			    "Max: 1; Min: 16(no compression); Default: 4");
 
 /* ------------------------------------------------------------------------
  * Driver initialization and cleanup
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index f14581b..a588e68 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -348,8 +348,9 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue,
 	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
 		goto done;
 
-	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
-		buf->buf.index, buf->state, buf->buf.bytesused);
+	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u/%u bytes).\n",
+		  buf->buf.index, buf->state,
+		  buf->buf.length, buf->buf.bytesused);
 
 	switch (buf->state) {
 	case UVC_BUF_STATE_ERROR:
@@ -371,6 +372,9 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue,
 		goto done;
 	}
 
+	if (buf->buf.bytesused > queue->max_used_lengh)
+		queue->max_used_lengh = buf->buf.bytesused;
+
 	list_del(&buf->stream);
 	__uvc_query_buffer(buf, v4l2_buf);
 
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index fc766b9..e595dd4 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -119,8 +119,10 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 		ctrl->dwMaxVideoFrameSize =
 			frame->dwMaxVideoFrameBufferSize;
 
-	if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) &&
-	    stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
+	if ((!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
+	      (format->fcc == V4L2_PIX_FMT_MJPEG)) &&
+	    (stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH ||
+	     stream->dev->quirks & UVC_QUIRK_FIX_JPEG_BANDWIDTH) &&
 	    stream->intf->num_altsetting > 1) {
 		u32 interval;
 		u32 bandwidth;
@@ -149,7 +151,11 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 		 * resolutions working while not preventing two simultaneous
 		 * VGA streams at 15 fps.
 		 */
-		bandwidth = max_t(u32, bandwidth, 1024);
+		if(!(stream->dev->quirks & UVC_QUIRK_DISABLE_URB_1024))
+			bandwidth = max_t(u32, bandwidth, 1024);
+
+		uvc_trace(UVC_TRACE_VIDEO, "Revrite dwMaxPayloadTransferSize %u"
+			  " to %u", ctrl->dwMaxPayloadTransferSize, bandwidth);	
 
 		ctrl->dwMaxPayloadTransferSize = bandwidth;
 	}
@@ -238,6 +244,21 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream,
 	uvc_fixup_video_ctrl(stream, ctrl);
 	ret = 0;
 
+	uvc_trace(UVC_TRACE_VIDEO, "%s: %s; bmHint: %u; bFormatIndex: %u; "
+		"bFrameIndex: %u; dwFrameInterval: %u; wKeyFrameRate: %u; "
+		"wCompQuality: %u; wCompWindowSize: %u; wDelay: %u; "
+		"dwMaxVideoFrameSize %u; dwMaxPayloadTransferSize: %u",
+		__func__, uvc_query_name(query), ctrl->bmHint,
+		ctrl->bFormatIndex,
+		ctrl->bFrameIndex,
+		ctrl->dwFrameInterval,
+		ctrl->wKeyFrameRate,
+		ctrl->wCompQuality,
+		ctrl->wCompWindowSize,
+		ctrl->wDelay,
+		ctrl->dwMaxVideoFrameSize,
+		ctrl->dwMaxPayloadTransferSize);
+
 out:
 	kfree(data);
 	return ret;
@@ -250,6 +271,21 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream,
 	__u16 size;
 	int ret;
 
+	uvc_trace(UVC_TRACE_VIDEO, "%s: %s; bmHint: %u; bFormatIndex: %u; "
+		"bFrameIndex: %u; dwFrameInterval: %u; wKeyFrameRate: %u; "
+		"wCompQuality: %u; wCompWindowSize: %u; wDelay: %u; "
+		"dwMaxVideoFrameSize %u; dwMaxPayloadTransferSize: %u",
+		__func__, probe ? "PROBE" : "COMMIT", ctrl->bmHint,
+		ctrl->bFormatIndex,
+		ctrl->bFrameIndex,
+		ctrl->dwFrameInterval,
+		ctrl->wKeyFrameRate,
+		ctrl->wCompQuality,
+		ctrl->wCompWindowSize,
+		ctrl->wDelay,
+		ctrl->dwMaxVideoFrameSize,
+		ctrl->dwMaxPayloadTransferSize);
+
 	size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
 	data = kzalloc(size, GFP_KERNEL);
 	if (data == NULL)
@@ -873,6 +909,24 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
 
 	if (free_buffers)
 		uvc_free_urb_buffers(stream);
+
+	/* uvc_uninit_video is colled two times at the stream finish,
+	 * so just make sure we print it only one time. */
+	if (stream->print_statistic) {
+		struct uvc_format *cur_format = stream->cur_format;
+		struct uvc_frame *cur_frame = stream->cur_frame;
+		struct uvc_streaming_control *ctrl = &stream->ctrl;
+		uvc_trace(UVC_TRACE_VIDEO, "Biggest used buffer: %u/%u. "
+			 "Format: %s %ux%u@%u.\n",
+			 cur_frame->dwMaxVideoFrameBufferSize,
+			 stream->queue.max_used_lengh,
+			 cur_format->name,
+			 cur_frame->wWidth,
+			 cur_frame->wHeight,
+			 10000000/ctrl->dwFrameInterval);
+		stream->queue.max_used_lengh = 0;
+		stream->print_statistic = 0;
+	}
 }
 
 /*
@@ -1071,6 +1125,8 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
 		}
 	}
 
+	stream->print_statistic = 1;
+
 	return 0;
 }
 
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 45f01e7..b963590 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -182,9 +182,11 @@ struct uvc_xu_control {
 #define UVC_QUIRK_BUILTIN_ISIGHT	0x00000008
 #define UVC_QUIRK_STREAM_NO_FID		0x00000010
 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT	0x00000020
+#define UVC_QUIRK_FIX_JPEG_BANDWIDTH	0x00000040
 #define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
 #define UVC_QUIRK_PROBE_DEF		0x00000100
 #define UVC_QUIRK_RESTRICT_FRAME_RATE	0x00000200
+#define UVC_QUIRK_DISABLE_URB_1024	0x00000400
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED		0x00000001
@@ -403,6 +405,9 @@ struct uvc_video_queue {
 
 	struct list_head mainqueue;
 	struct list_head irqqueue;
+
+	/* collect statistic */
+	unsigned int max_used_lengh;
 };
 
 struct uvc_video_chain {
@@ -462,6 +467,8 @@ struct uvc_streaming {
 
 	__u32 sequence;
 	__u8 last_fid;
+
+	unsigned int print_statistic;
 };
 
 enum uvc_device_state {
_______________________________________________
Linux-uvc-devel mailing list
Linux-uvc-devel@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel

Reply via email to