[GnomeMeeting-devel-list] Patch for v4l2 - removing multiple buffers, please review and test.



Hello guys and gals.

I had some problems getting my really cheap sn9c102-based webcam to
function with the otherwise fine work of Nicola Orru' on pwlib's
V4L2-plugin.

After some debugging and a (very short) time trying to figure out the
V4L2-API, I found that my cheap camera didn't handle mmap with multiple
buffers. I dug around a bit and discovered that the normal V4L-plugin
only use one buffer for mmap, so I decided to try this for V4L2 as well.

I cleaned it up a bit, removed all references to multiple buffers and it
worked flawlessly. I've both streamed from my webcam as well as CNN from
my bttv-card on the V4L2-plugin today ....without any hiccups.

Beware tho'. I've got almost 10 years of Linux-experience, but this is
my first attempt at programming devices.

I would appreciate if as many as possible could review and test this.
I'm not even sure if it's frowned upon, or if I broke something else by
using only one videobuffer. I might even have done something totally
stupid :)

As far as I can tell, 2 things still needs to be done with the
V4L2-plugin: 
- better device-detection, which Nicola is working on
- "Test Settings" in the druid hangs indefinitely. Someone(tm) needs to
look into which functions that needs.

Now I need to get back to my Master's thesis on the semantic web :)

-- 
Cheers,
 Heikki
diff -ru pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.cxx pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.cxx
--- pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.cxx	2004-10-27 12:02:54.000000000 +0200
+++ pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.cxx	2004-11-04 00:19:23.000000000 +0100
@@ -197,12 +197,12 @@
     struct v4l2_buffer buf;
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buf.index = 0;
+    buf.memory = V4L2_MEMORY_MMAP;
 
     if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) {
       PTRACE(3,"PVidInDev\tVIDIOC_QBUF failed : " << ::strerror(errno));
       return FALSE;
     }
-    buf.index = 0;
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
     if (::ioctl(videoFd, VIDIOC_STREAMON, &buf.type) < 0) {
@@ -211,14 +211,6 @@
     }
     started = TRUE;
 
-    // requeue all buffers
-    for (buf.index = 0; buf.index < videoBufferCount; buf.index++) {
-      PTRACE(3,"PVidInDev\tQBUF for index:" << buf.index);
-      if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) {
-	PTRACE(3,"PVidInDev\tQBUF failed : " << ::strerror(errno));
-	return FALSE;
-      }
-    }
   }
 
   return TRUE;
@@ -579,37 +571,32 @@
     return FALSE;
 
   struct v4l2_requestbuffers reqbuf;
-  reqbuf.count = 2; // we shouldn't need more
+  reqbuf.count = 1; // Some cameras don't handle more, and we don't need it anyway.
   reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   reqbuf.memory = V4L2_MEMORY_MMAP;
 
-  if (::ioctl(videoFd, VIDIOC_REQBUFS, &reqbuf) < 0 ||
-      reqbuf.count < 2 ||
-      reqbuf.count > NUM_VIDBUF) {
+  if (::ioctl(videoFd, VIDIOC_REQBUFS, &reqbuf) < 0) {
     PTRACE(3,"PVidInDev\tREQBUFS failed : " << ::strerror(errno));
     return FALSE;
   }
 
   struct v4l2_buffer buf;
   buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  buf.memory = V4L2_MEMORY_MMAP;
+  buf.index = 0;
+  if (::ioctl(videoFd, VIDIOC_QUERYBUF, &buf) < 0) {
+    PTRACE(3,"PVidInDev\tQUERYBUF failed : " << ::strerror(errno));
+    return FALSE;
+  }
 
-  videoBufferCount = reqbuf.count;
-  for (buf.index = 0; buf.index < videoBufferCount; buf.index++) {
-    if (::ioctl(videoFd, VIDIOC_QUERYBUF, &buf) < 0) {
-      PTRACE(3,"PVidInDev\tQUERYBUF failed : " << ::strerror(errno));
-      return FALSE;
-    }
-
-    if ((videoBuffer[buf.index] = (BYTE *)::mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, videoFd, buf.m.offset)) == MAP_FAILED) {
-      PTRACE(3,"PVidInDev\tmmap failed : " << ::strerror(errno));
-      return FALSE;
-    }
+  if ((videoBuffer = (BYTE *)::mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, videoFd, buf.m.offset)) == MAP_FAILED) {
+    PTRACE(3,"PVidInDev\tmmap failed : " << ::strerror(errno));
+    return FALSE;
   }
 
   isMapped = TRUE;
 
-  PTRACE(7,"PVidInDev\tset mapping for " << videoBufferCount << " buffers, fd=" << videoFd);
-
+  PTRACE(7,"PVidInDev\tset mapping for 1 buffer, fd=" << videoFd);
 
   return TRUE;
 }
@@ -621,13 +608,14 @@
     return;
 
   struct v4l2_buffer buf;
+  buf.index = 0;
   buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  buf.memory = V4L2_MEMORY_MMAP;
 
   for (buf.index = 0; ; buf.index++) {
     if (::ioctl(videoFd, VIDIOC_QUERYBUF, &buf) < 0)
       break;
-
-    ::munmap(videoBuffer[buf.index], buf.length);
+    ::munmap(videoBuffer, buf.length);
   }
 
   isMapped = FALSE;
@@ -714,9 +702,9 @@
   // If converting on the fly do it from frame store to output buffer,
   // otherwise do straight copy.
   if (converter != NULL)
-    converter->Convert(videoBuffer[buf.index], buffer, bytesReturned);
+    converter->Convert(videoBuffer, buffer, bytesReturned);
   else {
-    memcpy(buffer, videoBuffer[buf.index], buf.bytesused);
+    memcpy(buffer, videoBuffer, buf.bytesused);
     if (bytesReturned != NULL)
       *bytesReturned = buf.bytesused;
   }
diff -ru pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.h pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.h
--- pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.h	2004-10-27 12:02:54.000000000 +0200
+++ pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.h	2004-11-04 00:17:22.000000000 +0100
@@ -91,9 +91,7 @@
   BOOL   canSelect;
   BOOL   canSetFrameRate;
   BOOL   isMapped;
-#define NUM_VIDBUF 4
-  BYTE * videoBuffer[NUM_VIDBUF];
-  uint    videoBufferCount;
+  BYTE * videoBuffer;
 
   int    videoFd;
   int    frameBytes;

Attachment: signature.asc
Description: Dette er en digitalt signert meldingsdel



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]