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