On 04/29/2010 12:40 PM, Dennis Muhlestein wrote:
One idea I've been toying with is to add a semaphore around submitting
the URBs.
In uvc_video.c, where the URBs are submitted, I'd acquire a semephore
for each device currently submitting URBs. The semaphore would limit the
number of devices to whatever number I decide can safely submit URBs
simultaneously on the bus without throwing out of space errors.
I did an initial test of this and it looks promising. I can configure
all the cameras. As long as I don't submit the URBs for the number of
devices beyond that which will work at the same time, the other cameras
simply drop the data.
I'm not sure the best places to control the locking and unlocking of the
semaphore are. Right now, I lock it before submitting URBs in
uvc_init_video. In uvc_video_complete, I unlock it and relock it if the
buffer is complete (allowing another camera to acquire it and capture a
frame).
Anyway, it isn't working perfectly yet but I think I can debug it and at
least get to a point where I know if it's worth pursuing. I'm curious if
anyone can provide thoughts or alternatives.
I have two solutions that I've come up with this so far.
1) Modify the uvc_video.c to queue urbs in a list in the urb completion
handler. A driver level semaphore controls the number of currently
submitting cameras. You can adjust the initial sem_count in
uvc_driver.c. Ideally, that would be a module parameter but I'm just
getting things to work.
I found capture speeds quite a bit slower than I'd like with this method
though. I can capture with 8 cameras at 10 FPS without overwhelming the
ISO bus but if I change to 15 FPS I can only capture with 3 cameras at a
time. Adding the patch, I then can configure and capture from all 8
cameras running at 15 FPS but only submitting URBs for 3 at a time.
Depending on how many frames I let those cameras capture I got captured
frame rates from around 4 to 6.
I'm attaching the patch in case anyone wants to play with this or
suggest ways to improve it. One thing I had a problem with is that it
seems some of the capture images are corrupted. This patch was against
2.6.27.2. A little old I know but I'm working on an embedded device.
2) I modified ehci-sched.c to not raise the ENOSPC error. That solution
actually lets me capture on all 8 cameras at 15 FPS. This has other
implications though and I'm not sure it is a very good solution. It
does tell me that perhaps the Linux ISO scheduler could perhaps use look
through. One major discrepancy is that bandwidth is allocated based on
the max packet size I think but for my compressed images (MJPG) each
frame is only a fraction of the max allocated bandwidth.
-Dennis
diff --git a/uvc_driver.c b/uvc_driver.c
index 7e10203..6445ec1 100644
--- a/uvc_driver.c
+++ b/uvc_driver.c
@@ -1963,8 +1963,12 @@ static int __init uvc_init(void)
INIT_LIST_HEAD(uvc_driver.devices);
INIT_LIST_HEAD(uvc_driver.controls);
+INIT_LIST_HEAD(uvc_driver.wait_urbs);
mutex_init(uvc_driver.open_mutex);
mutex_init(uvc_driver.ctrl_mutex);
+//mutex_init(uvc_driver.urb_mutex);
+uvc_driver.urb_lock = SPIN_LOCK_UNLOCKED;
+uvc_driver.sem_count=3;
uvc_ctrl_init();
diff --git a/uvc_v4l2.c b/uvc_v4l2.c
index b27cf5c..6376759 100644
--- a/uvc_v4l2.c
+++ b/uvc_v4l2.c
@@ -427,6 +427,10 @@ static int uvc_v4l2_open(struct inode *inode, struct file
*file)
goto done;
}
+video-has_sem=0;
+video-sent_urbs=0;
+video-release_on_no_urbs=0;
+video-sem_frame =0;
handle-device = video;
handle-state = UVC_HANDLE_PASSIVE;
file-private_data = handle;
diff --git a/uvc_video.c b/uvc_video.c
index 6854ac7..f1b9673 100644
--- a/uvc_video.c
+++ b/uvc_video.c
@@ -26,6 +26,9 @@
#include uvcvideo.h
+// predef
+static void uvc_video_frame_complete(struct uvc_video_device *);
+
/*
* UVC Controls
*/
@@ -415,6 +418,7 @@ static void uvc_video_decode_end(struct uvc_video_device
*video,
buf-state = UVC_BUF_STATE_DONE;
if (video-dev-quirks UVC_QUIRK_STREAM_NO_FID)
video-last_fid ^= UVC_STREAM_FID;
+uvc_video_frame_complete(video);
}
}
@@ -524,13 +528,161 @@ static void uvc_video_decode_bulk(struct urb *urb,
}
}
+
+/**
+ * Incs the resource count for allows video devices
+ * if the specified video device currently has a
+ * resource locked.
+ **/
+static void uvc_video_frame_complete(struct uvc_video_device *video) {
+
+ // mutex_lock ( uvc_driver.urb_mutex );
+ unsigned long flags;
+ spin_lock_irqsave ( uvc_driver.urb_lock, flags );
+ //uvc_printk ( KERN_WARNING, Frame Complete: %s\n,
video-dev-udev-serial );
+ video-sem_frame += 1;
+ if ( video-has_sem video-sem_frame 2 ) {
+if (!video-sent_urbs) {
+video-has_sem = 0;
+